Imprimir linha após a enésima ocorrência de uma correspondência

8

Eu estou olhando para exibir a linha 4598 no arquivo a seguir. Efetivamente, quero exibir a linha APÓS a enésima ocorrência de uma correspondência. Nesse caso, a linha após a 3ª ocorrência de <Car>. Como faço para fazer isso?

<Car>
10456
</Car>
<Car>
70192
</Car>
<Car>
4598
</Car>
DJ180
fonte
1
Embora possa ser possível conseguir o que você quer usar sed, awkou mesmo grep, é aconselhável fazer uso de um analisador XML.
devnull
XML só foi utilizado para o exemplo, o texto pode ser qualquer formato
DJ180

Respostas:

10
awk -v n=3 '/<Car>/ && !--n {getline; print; exit}'

Ou:

awk '/<Car>/ && ++n == 3 {getline; print; exit}'

Para passar o padrão de pesquisa como uma variável:

var='<car>'
PATTERN="$var" awk -v n=3 '
  $0 ~ ENVIRON["PATTERN"] && ++n == 3 {getline; print; exit}'

Aqui, em ENVIRONvez de -vcomo -vexpande, as seqüências de escape de barra invertida e barras invertidas são frequentemente encontradas em expressões regulares (portanto, é necessário duplicar -v).

O GNU awk4.2 ou superior permite atribuir variáveis ​​como regexps de tipo forte . Desde que seu modo POSIX não esteja ativado (por exemplo, através da $POSIXLY_CORRECTvariável de ambiente, você pode:

# GNU awk 4.2 or above only, when not in POSIX mode
gawk -v n=3 -v pattern="@/$var/" '
  $0 ~ pattern && ++n == 3 {getline; print; exit}'
Stéphane Chazelas
fonte
Como passar o padrão de pesquisa também como uma variável no comando acima
WanderingMind
@WanderingMind, consulte editar.
Stéphane Chazelas
4

Aqui está um perl:

perl -ne 'print && exit if $c==3; $c++ if /<Car>/;' file 

Com o GNU grep, você também pode analisar sua saída como:

grep -A 1 -m 3 '<Car>' file | tail -n 1

De man grep:

-A NUM, --after-context=NUM
          Print NUM lines of trailing context after matching lines.  
          Places a line containing a group separator (--) between 
          contiguous  groups  of  matches.          
-m NUM, --max-count=NUM
          Stop reading a file after NUM matching lines.  
terdon
fonte
3

Com GNU awkvocê pode fazer:

gawk -v RS='</Car>' 'NR==3 && $0=$2' inputFile
jaypal singh
fonte
1

Aqui está outra maneira de sed:

sed -n '/<Car>/{x;/.\{2\}/{x;$!{n;p};q};s/.*/&./;x}' infile

Isso está usando o espaço de espera para contar.
Cada vez que encontra uma linha correspondente, <Car>ele xmuda os buffers e verifica se há exatamente N-1 ocorrências de um caractere no buffer de espera. Se a verificação for bem-sucedida, ela é xalterada novamente e, se não estiver na última linha, puxa a nlinha ext e pcria o espaço do padrão e, em seguida, qsai. Caso contrário, ele adiciona outro .caractere ao espaço de espera ee xvolta.

don_crissti
fonte
0

Aqui está uma solução simples de linha de comando.

grep -F -A1 '<Car>' filename | grep -E -v '<Car>|--' | tail -n +3 |head -n +1

Se você alterar o valor de +3 depois tail, poderá especificar qualquer enésima linha.

bsd
fonte
Não sabe por que você adicionou as tags sed, awk, etc. Se você deseja uma solução usando um aplicativo específico, utilitário, especifique-o em questão ou título.
BSD