Imprime entre dois padrões somente quando o primeiro padrão ocorre pela segunda vez

3

Eu quero imprimir a saída entre dois padrões e o primeiro padrão deve ser a segunda coincidência no arquivo.

Exemplo -

test.txt

start one
text_1   
end
start two
text_2
end 
start three
text_3
end

Aqui, o primeiro padrão é start e o segundo padrão é end . O padrão start deve corresponder ao padrão da segunda vez no arquivo. Então saída deve ser

start two
text_2
end
    
por Vishal 03.03.2017 / 08:36

4 respostas

2

Com awk , facilmente extensível a qualquer registro th :

awk '/start/ && ++n == 2, /end/' < file

imprimia as linhas da segunda ocorrência de start para a primeira ocorrência de end depois disso.

Para imprimir o segundo registro start to end (faria diferença se houvesse start , start , end sequencias):

awk '
  /start/, /end/ {
    if (!seen) {seen = 1; n++}
    if (n == 2) print
    if (/end/) seen = 0
  }' < file

Ou:

awk '
  !inside && /start/ {inside = 1; n++}
  !inside {next}
  n == 2
  /end/ {inside = 0}' < file 
    
por 03.03.2017 / 17:59
1

com sed

sed -n '/start/,/end/n;/start/,/end/{p;/end/q}' file

Explicação:

  • -n suprime a saída
  • primeiro /start/,/end/n extrai primeiro bloco de início a fim, mas não faz nada (via n )
  • depois para o segundo bloco de início a fim /start/,/end/ print e saia assim que o final for atingido p;/end/q
por 03.03.2017 / 09:29
0

Neste caso particular - quando a entrada consiste apenas em /start/,/end/ , você pode simplesmente fazer

sed '1,/end/d;//q' infile

Se houver outras linhas entre esses blocos (não correspondentes a end ), então

sed '1,/end/d;/start/,/end/!d;/end/q' infile

Para o caso mais geral, quando o bloco a ser extraído é o n th que você pode executar:

n=5
awk  -vc=$n '/start/{i++};{if (i==c){print;if (/end/){exit}}}' infile
    
por 03.03.2017 / 12:47
0
sed -ne '
   /^start/,/^end/!d; # skip non-interesting block
   /^start/H;         # increment hold counter
   G;/\n.*\n.*\n/!d;  # check if 2nd block reached?
   P;/^end/q;         # we"re in 2nd block so print & quit on /end/
' yourfile

perl -l -0777ne 'print+(/^start.*?\nend[^\n]*$/msg)[1]' yourfile
    
por 03.03.2017 / 17:34