Separador entre instruções no awk

6

Do manual do Gawk:

When awk statements within one rule are short, you might want to put more than one of them on a line. This is accomplished by separating the statements with a semicolon (‘;’). This also applies to the rules themselves. Thus, the program shown at the start of this section could also be written this way:

/12/ { print $0 } ; /21/ { print $0 }

NOTE: The requirement that states that rules on the same line must be sepa rated with a semicolon was not in the original awk language; it was added for consistency with the treatment of statements within an action.

Mas já vi o link

awk '$2=="no"{$3="N/A"}1' file

Não são $2=="no"{$3="N/A"} e 1 duas declarações? por que eles não estão separados por nada?

Obrigado.

    
por Tim 17.07.2017 / 21:21

3 respostas

8

Muito boa pergunta! Eu acho que a chave é esta: "Assim, o programa mostrado no início desta seção também poderia ser escrito desta forma:"

Não é obrigatório que seja escrito desta maneira. É um tipo de caminho alternativo. Isso significa (e foi provado em ação) que as afirmações abaixo estão corretas:

$ awk '/12/ { print $0 } /21/ { print $0 }' file
$ awk '/12/ { print $0 } ; /21/ { print $0 }' file

Acho que esse uso de ponto-e-vírgula é para cobrir o código realmente idiomático, por exemplo, casos em que omitimos a parte da ação e queremos aplicar várias regras na mesma linha:

$ awk '/12//21/' file
awk: cmd. line:2: /12//21/
awk: cmd. line:2:         ^ unexpected newline or end of string

Nesse caso, usar um ponto-e-vírgula é obrigatório para separar regras (= condições):

$ awk '/12/;/21/' file

Como a parte {action} é omitida nas duas regras / ambas as condições, a ação padrão será executada para cada regra = {print $0}

    
por 17.07.2017 / 22:13
6

No gawk, as duas citações do manual descrevem o problema:

An action consists of one or more awk statements, enclosed in braces (‘{…}’). Each statement specifies one thing to do. The statements are separated by newlines or semicolons.

Um ponto-e-vírgula é um " separador ", mas não um " terminator ".
O único terminador válido de uma ação é uma chave de fechamento ( } ).

Portanto, o que segue uma chave de fechamento de ação ( } ) deve ser algum outro padrão {action}

No "man mawk " há alguma outra descrição que pode ajudar a esclarecer o que o awk deve fazer:

Statements are terminated by newlines, semi-colons or both. Groups of statements such as actions or loop bodies are blocked via { ... } as in C. The last statement in a block doesn't need a terminator.

O "man nawk " explica da seguinte forma:

The pattern comes first, and then the action. Action statements are enclosed in { and }.

E, se você quiser ficar por dentro dos detalhes, leia a descrição POSIX :

action           : '{' newline_opt                             '}'
                 | '{' newline_opt terminated_statement_list   '}'
                 | '{' newline_opt unterminated_statement_list '}'
                 ;

E pesquise o que é uma lista de instruções "não terminada".

Ou, mais simples, pesquise Ação para ler:

Any single statement can be replaced by a statement list enclosed in curly braces. The application shall ensure that statements in a statement list are separated by or characters.

Novamente: are separated by <newline> or <semicolon> characters

    
por 18.07.2017 / 04:24
3

O ponto e vírgula entre os blocos condicionais parece ser opcional; apenas os pontos-e-vírgulas entre as declarações dentro dos blocos parecem ser obrigatórios:

$ echo -e "foo\nbar" | gawk '/foo/ { print "foo found" } /bar/ {print "bar found"}'
foo found
bar found
$ echo -e "foo\nbar" | gawk '/foo/ { print "foo found" }; /bar/ {print "bar found"}'
foo found
bar found
$ echo -e "foo\nbar" | gawk '/foo/ { print "foo found"; print "whee" }'
foo found
whee
$ echo -e "foo\nbar" | gawk '/foo/ { print "foo found" print "whee" }'
gawk: cmd. line:1: /foo/ { print "foo found" print "whee" }
gawk: cmd. line:1:                           ^ syntax error

No entanto, quando o bloco de código real entre dois condicionais é omitido em favor do padrão (ou seja, {print} ), o ponto-e-vírgula se torna necessário:

$ echo -e "foo\nbar" | gawk '/foo/ /bar/'
gawk: cmd. line:2: /foo/ /bar/
gawk: cmd. line:2:            ^ unexpected newline or end of string
$ echo -e "foo\nbar" | gawk '/foo/; /bar/'
foo
bar
    
por 17.07.2017 / 22:13

Tags