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>

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}'

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.  

3

Com GNU awkvocê pode fazer:

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

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.


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.


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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.