AWK imprimir do padrão ao padrão

0
arquivo

:

string1 string2 string3 string4 string5 string6  
string3 string1 string2 string4 string5 string6  
string6 string3 string2 string4 string1 string5

expectativa:

string2 string3 string4 string5  
string2 string4 string5  
string2 string4 string1 string5

Padrão de correspondência = string1
Como imprimir linhas de correspondência, mas apenas de string2 a string5 com awk ?

Infelizmente, isso não está sendo processado na fila:

 awk '/string2/,/string5/' file 

Vamos supor que há poucas linhas longas com string2 e string5 em lugares diferentes.

    
por EdiD 05.03.2017 / 19:08

3 respostas

3

Você pode usar as funções index e match do awk, por exemplo

awk 'match($0,/string5/) {
  START2 = index($0,"string2");
  print substr($0,START2,RSTART+RLENGTH-START2)
}' file

Ex.

$ mawk 'match($0,/string5/) {
  START2 = index($0,"string2");
  print substr($0,START2,RSTART+RLENGTH-START2)
}' file
string2 string3 string4 string5
string2 string4 string5
string2 string4 string1 string5

Observe que isso pressupõe que string2 existirá em todas as linhas em que string5 existe - se não for esse o caso, você precisará verificar o valor de index($0,"string2") e agir de acordo.

    
por steeldriver 05.03.2017 / 19:20
3

Efetivamente, o que você deseja fazer é iterar sobre cada campo e "ativar" a impressão com uma variável se o resultado for encontrado. Assim, o que você precisa é uma variável de sinalização e loop:

$ cat file.txt
string1 string2 string3 string4 string5 string6
string3 string1 string2 string4 string5 string6
string6 string3 string2 string4 string1 string5

$ awk '{flag=0;for(i=1;i<=NF;i++){ if($i=="string2") flag=1; if($i=="string6") flag=0;  if(flag)printf "%s%s",$i,FS;};print"";}' file.txt  
string2 string3 string4 string5 
string2 string4 string5 
string2 string4 string1 string5 

O que acontece aqui é que todo o bloco de código será executado para cada linha. Em cada linha estamos iterando do primeiro campo para o último. Inicialmente, definimos a variável flag como 0 e, em seguida, examinamos cada campo. Se o campo contiver a "string2" desejada, o sinalizador será definido como 1 e se for "string6" (que é o único quando queremos parar) - o sinalizador será definido como 0; finalmente, se a instrução verificará se o sinalizador está configurado e imprime o campo atual anexado ao separador de campo (representado pela variável FS). Depois de tudo ter sido impresso, também inserimos uma nova linha via comando print "" .

No caso de você ter linhas sem correspondência, o comando acima imprimirá linhas em branco. Você pode atenuar isso por meio da adição do padrão de pesquisa, que limitará a execução do bloco de códigos somente quando houver um padrão encontrado na string:

$ cat file.txt
string1 string2 string3 string4 string5 string6
blah blah
string3 string1 string2 string4 string5 string6
string6 string3 string2 string4 string1 string5

$ awk '$0~"string2"{flag=0;for(i=1;i<=NF;i++){ if($i=="string2") flag=1;  if(flag)printf "%s%s",$i,FS;};print"";}' file.txt
string2 string3 string4 string5 string6 
string2 string4 string5 string6 
string2 string4 string1 string5 

Como alternativa, podemos usar uma variável extra com o mesmo resultado:

$ awk '{j=0;f=0;for(i=1;i<=NF;i++){if($i=="string2"){j=1;f=1};if(f)printf "%s%s",$i,FS;};if(j)print"";}' file.txt        
string2 string3 string4 string5 string6 
string2 string4 string5 string6 
string2 string4 string1 string5
    
por Sergiy Kolodyazhnyy 05.03.2017 / 19:26
1

Usando o grep:

grep -Po '\bstring2.*string5\b' file.txt
    
por JJoao 28.03.2017 / 13:31