Ao usar o awk / pattern / {imprimir “text”} / patern / {print “”} existe um padrão ELSE?

21

Digamos que eu tenha um arquivo de texto como:

R1 12 324 3453 36 457 4 7 8
R2 34 2342 2525 25 25 26 26 2 2
R3 23 2342 32 52 54 543 643 63
R4 25 234 2342 4 234242

Eu quero usar awk para processar essas linhas de maneira diferente, como

awk '/R1/ { print "=>" $0} /R2/ { print "*" $0} '

e eu também quero imprimir todas as outras linhas como elas são (sem fazer duplicatas das linhas que eu já processei), basicamente eu preciso de um /ELSE/ { print $0} no final da minha linha awk . / p>

Existe tal coisa?

    
por Ali 28.11.2011 / 20:09

3 respostas

27

Abordagem simplificada com awk

awk '/R1/ {print "=>" $0;next} /R2/{print "*" $0;next} 1' text.file

[jaypal:~/Temp] cat text.file 
R1 12 324 3453 36 457 4 7 8
R2 34 2342 2525 25 25 26 26 2 2
R3 23 2342 32 52 54 543 643 63
R4 25 234 2342 4 234242

[jaypal:~/Temp] awk '/R1/ { print "=>" $0;next} /R2/{print "*" $0;next}1' text.file
=>R1 12 324 3453 36 457 4 7 8
*R2 34 2342 2525 25 25 26 26 2 2
R3 23 2342 32 52 54 543 643 63
R4 25 234 2342 4 234242
[jaypal:~/Temp] 

Desvinculação do padrão {Action} Declarações:

  • /R1/ { print "=>" $0;next} : Isso significa que as linhas com /R1/ da ação de impressão => serão feitas. next significa que o resto das instruções do awk serão ignoradas e a próxima linha será analisada.

  • /R2/{print "*" $0;next} : Isso significa que as linhas correspondentes à pattern /R2/ da ação de impressão * serão feitas. Quando awk do processamento for iniciado, a primeira instrução pattern {action} será ignorada, pois o pattern /R1/ não será verdadeiro para as linhas que tiverem /R2/ . Então, a segunda declaração pattern {action} será feita na linha. next significaria novamente que não queremos mais processamento e awk irá para a próxima linha.

  • 1 imprime todas as linhas. Quando apenas uma condição é fornecida sem {action} , o awk usa como padrão {print} . Aqui a condição é 1 , que é interpretada como verdadeira, então sempre é bem-sucedida. Se chegarmos a este ponto, é porque o primeiro e o segundo pattern {action} foram ignorados ou ignorados (para linhas que não contêm /R1/ e /R2/ ), então a ação de impressão padrão será feita para as linhas restantes.

por 28.11.2011 / 22:42
6

awk implementa os suspeitos usuais quando se trata de condicionais. É uma boa ideia usar printf em vez de print para o trabalho que você deseja fazer no jogo.

awk '{ if (/^R1/) { printf("=> %s\n", $0) } else if (/^R2/) { printf("* %s\n", $0) } else { print $0 } }'
    
por 28.11.2011 / 20:35
3

Chris Down já mostrou como você pode obter um else para expressões regulares usando uma instrução 'if' explícita em um bloco. Você também pode obter o mesmo efeito de outras maneiras, embora sua solução seja provavelmente melhor.

Um é escrever um terceiro regex que corresponderá apenas ao texto não correspondido pelos outros; no seu caso, seria algo como isto:

awk '/^R1/ { print "=>" $0}
     /^R2/ { print "*" $0}
     /^[^R]/ || /^R[^12]/ { print $0 } '

Note que isso usa regexps ancoradas - o ^ no início do regexps só coincidirá no começo de uma linha - seus padrões originais não fizeram isso, o que atrasa um pouco a correspondência, pois ele verifica todos os caracteres em um linha em vez de pular até a próxima linha. O terceiro caso ("else") corresponderá a uma linha que comece com algum caractere que não seja 'R' ([^ R]) ou que comece com um 'R' seguido por um caractere que não seja '1' ou ' 2 '(R [^ 12]). Os dois significados diferentes de ^ são um pouco confusos, mas esse erro foi cometido há muito tempo e não será alterado em breve.

Para usar expressões regulares complementares, elas realmente precisam ser ancoradas, caso contrário, o [^ R] corresponderia, por exemplo, o 1 seguinte. Para regexps muito simples como você, essa abordagem pode ser útil, mas à medida que as expressões regulares se tornam mais complexas, essa abordagem se tornará incontrolável. Em vez disso, você pode usar variáveis de estado para cada linha, assim:

awk '{ handled = 0 }
     /^R1/ { print "=>" $0; handled = 1}
     /^R2/ { print "*" $0; handled = 1}
     { if (!handled) print $0 } '

Este conjunto é tratado como zero para cada nova linha, em seguida, para 1 se corresponder a qualquer um dos dois expressões regulares e, finalmente, se ainda for zero, executa a impressão $ 0.

    
por 28.11.2011 / 20:40

Tags