Posso usar uma variável que armazena uma expressão regular sempre que uma expressão regular é esperada?

1

No Awk, quando eu armazeno uma expressão regular em uma variável, posso usar a variável sempre que uma expressão regular é esperada?

A linguagem de programação AWK da Aho diz

Note that the string-matching pattern

/Asia/ 

is a shorthand for

$O ~ /Asia/

Eu tenho um arquivo de texto:

$ cat f1
line 1; li
ne
2
line 3
lin
e 4

Por que as duas maneiras a seguir funcionam

$ awk -v pat='in' '{if (match($0, pat)) print $0; } ' f1
line 1; li
line 3
lin
$ awk -v pat='in' ' $0 ~ pat {print $0} ' f1
line 1; li
line 3
lin

enquanto o seguinte não é

$ awk -v pat='in' ' pat {print $0} ' f1
line 1; li
ne
2
line 3
lin
e 4

?

Obrigado.

    
por Tim 15.11.2018 / 21:36

1 resposta

3

Apenas /foo/ sozinho é curto para $0 ~ /foo/ .

Em ... ~ /.../ ou match(/.../, ...) ..., é apenas alguma forma de operador de cotação para regexps, enquanto em outros contextos, é mais um operador que resolve um número (0 ou 1).

Esse duplo significado pode ser um pouco confuso. Há muitos desses significados / ambigüidades duplos em awk .

/foo/ se expande para 1 ou 0, dependendo se $0 corresponde ou não à foo regexp, mas "1" ~ /foo/ não é "1" ~ "1" quando $0 coincide com foo , aqui /foo/ é não mais curto para ($0 ~ /foo/). In the case of "1" ~ (/ foo /) or "1" ~ + / foo / ', você verá que o comportamento varia entre as implementações.

var é apenas var .

var como uma condição significa verdadeiro se a variável for numérica ou uma cadeia numérica e for resolvida para um número diferente de zero ou se for uma cadeia e for resolvida para uma cadeia não vazia.

as variáveis declaradas com -v var=value são aquelas que podem ser consideradas cadeias numéricas se parecerem com números e cadeias de outra forma.

awk -v var=in 'var {print "x"}'

imprime x para cada registro porque in não se parece com um número e não é a sequência vazia.

awk -v var=0 'var {print "x"}'

Não imprimirá x , enquanto:

awk 'BEGIN{var = "0"}; var {print "x"}'

imprime x para cada registro, pois var foi explicitamente declarado como uma variável de string. Então, embora pareça um número, não é considerado como tal.

Esse é outro desses significados duplos. Uma variável pode ser considerada numérica ou string dependendo do contexto. Veja também > que, dependendo do contexto, é tomado como um operador de comparação ou um operador de redirecionamento (que, novamente, várias situações ambíguas onde o comportamento varia entre implementações).

Note que você também pode fazer coisas como:

awk '{print /foo/ + /bar/}'

Qual é o mesmo que:

awk '{print ($0 ~ /foo/) + ($0 ~ /bar/)}'

Mas se estiver usando concatenação em vez de +

awk '{print /foo/ /bar/}'

isso não funciona, pois há novamente uma ambiguidade entre o operador /RE/ e o operador / division. Em caso de dúvida, use parêntesis:

awk '{print (/foo/) (/bar/)}'

A propósito, você deve evitar usar -v para armazenar regexps ou qualquer coisa que possa conter barras invertidas, já que sequências de escape ANSI são expandidas nelas. Em vez disso, você deve usar variáveis de ambiente:

RE='\.txt$' awk '$0 ~ ENVIRON["RE"] {...}'

por exemplo.

    
por 15.11.2018 / 21:51

Tags