Stampa la riga dopo l'ennesima occorrenza di una corrispondenza


8

Sto cercando di visualizzare la riga 4598 nel seguente file. In effetti, voglio visualizzare la riga DOPO l'ennesima occorrenza di una corrispondenza. In questo caso, la riga dopo la 3a occorrenza di <Car>. Come posso procedere?

<Car>
10456
</Car>
<Car>
70192
</Car>
<Car>
4598
</Car>

1
Mentre potrebbe essere possibile ottenere ciò che si vuole utilizzare sed, awko addirittura grep, si consiglia di fare uso di un parser XML.
Devnull

XML è stato utilizzato solo per l'esempio, il testo può essere di qualsiasi formato
DJ180,

Risposte:


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

O:

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

Per passare il modello di ricerca come variabile:

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

Qui usando ENVIRONinvece di -vcome si -vespandono le sequenze di backslash-escape e le backslash si trovano spesso nelle espressioni regolari (quindi dovrebbe essere raddoppiato con -v).

GNU awk4.2 o successivo ti consente di assegnare variabili come regexps tipizzati in modo forte . Finché la modalità POSIX non è abilitata (ad esempio tramite la $POSIXLY_CORRECTvariabile di ambiente, è possibile eseguire:

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

Come passare il modello di ricerca anche come variabile nel comando sopra
WanderingMind

@WanderingMind, vedi modifica.
Stéphane Chazelas,

4

Eccone uno perl:

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

Con GNU grep, puoi anche analizzarne l'output come:

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

Da 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

Con GNU awkte puoi fare:

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

1

Ecco un altro modo con sed:

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

Questo sta usando lo spazio di attesa per contare.
Ogni volta che incontra una linea corrispondente <Car>, xcambia i buffer e verifica se ci sono esattamente N-1 occorrenze di un personaggio nel buffer di mantenimento. Se il controllo ha esito positivo, xcambia di nuovo e, se non sull'ultima riga, inserisce la nlinea ext e psfilaccia lo spazio del motivo, quindi lo qusa. Altrimenti aggiunge solo un altro .carattere allo spazio di attesa e xritorna indietro.


0

Ecco una semplice soluzione da riga di comando.

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

Se si modifica il valore di +3 dopo tail, è possibile specificare qualsiasi ennesima riga.


Non sono sicuro del motivo per cui hai aggiunto i tag, sed, awk, ecc. Se desideri una soluzione utilizzando un'app specifica, un'utilità, devi specificarla nella domanda o nel titolo.
bsd
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.