Stampa la riga corrispondente e l'ennesima riga dalla riga corrispondente


18

Sto provando a stampare la linea abbinata e la 4a linea dalla linea abbinata (linea contenente l'espressione che sto cercando).

Ho usato il seguente codice: sed -n 's/^[ \t]*//; /img class=\"devil_icon/,4p' input.txt

Ma questo stampa solo la linea abbinata.

Questo stampa solo la 4a riga. awk 'c&&!--c;/img class=\"devil_icon/{c=4}' input.txt

Devo stampare sia la riga corrispondente sia solo la 4a riga.


Usa egrep "pattern" -A4
Valentin Bajrami il

@ val0x00ff che stampa anche le linee tra di loro .. cioè: stampa le 4 righe successive a partire dalla linea abbinata
debal

stai dicendo "Sto provando a stampare la linea abbinata e la 4a linea dalla linea abbinata". Questo grep -A 4 "pattern" file | sed -n '4p'fa esattamente quello che vuoi, a meno che non ti fraintenda
Valentin Bajrami,

no non lo fa. L'output del codice sopra era </td>che non è la 4a riga
debal

Risposte:


18

In awk, lo faresti come segue

awk '/pattern/{nr[NR]; nr[NR+4]}; NR in nr' file > new_file`

o

awk '/pattern/{print; nr[NR+4]; next}; NR in nr' file > new_file`

Spiegazione

La prima soluzione trova tutte le linee corrispondenti pattern. Quando trova una corrispondenza, memorizza il numero di record ( NR) nella matrice nr. Memorizza anche il 4 ° record dallo NRstesso array. Questo è fatto dal nr[NR+4]. Ogni record ( NR) viene quindi verificato per vedere se è presente nrnell'array, in tal caso il record viene stampato.

La seconda soluzione funziona essenzialmente allo stesso modo, tranne quando incontra la patternriga stampata, quindi memorizza il 4 ° record davanti ad essa nell'array nr, quindi passa al record successivo. Quindi quando awkincontra questo 4 ° record, il NR in nrblocco verrà eseguito e successivamente stampa questo record +4.

Esempio

Ecco un file di dati di esempio, sample.txt.

$ cat sample.txt 
1
2
3
4 blah
5
6
7
8
9
10 blah
11
12
13
14
15
16

Utilizzando la prima soluzione:

$ awk '/blah/{nr[NR]; nr[NR+4]}; NR in nr' sample.txt 
4 blah
8
10 blah
14

Utilizzando la seconda soluzione:

$ awk '/blah/{print; nr[NR+4]; next}; NR in nr' sample.txt 
4 blah
8
10 blah
14

3
Bello, +1. Stai usando molte awkscorciatoie qui, potresti aggiungere una breve spiegazione (cose come la stampa implicita in awk e che gli array sono associativi ecc.)?
terdon

d'accordo con @terdon per favore potresti spiegare un po 'il codice.
Debal,

@slm Grazie per aver migliorato e fornito la risposta completa!
Valentin Bajrami,

1
Grazie per la risposta, ho imparato anche qualcosa di nuovo.
slm

4
sed -n 's/^[ \t]*/; /img class=\"devil_icon/,+4 { 3,5d ; p }' input.txt

Sto semplicemente aggiungendo una cancellazione delle righe appropriate, prima di stampare { 3,5d ; p }.


la tua espressione produce un errore: sed: -e expression #1, char 18: unknown option to s'`
minerali

4

Puoi provare l' -Aopzione con grep, che specifica quante righe dopo la riga corrispondente devono essere stampate. Abbinalo a questo sede otterrai le linee richieste.

grep -A 4 pattern input.txt | sed -e '2,4d'

Usando sed, cancelliamo dalla seconda riga fino alla quarta.


3
Ciò presuppone una singola corrispondenza di patternnel file.
terdon

2

Ecco un modo in Perl che può gestire un numero arbitrario di righe corrispondenti:

perl -ne '/pattern/ && do{$c=$.; print}; $.==$c+4 && print' file > new_file`

In Perl. la variabile speciale $.è il numero di riga corrente. Quindi, ogni volta che trovo una corrispondenza di riga pattern, la stampo e ne salvo il numero di riga $c. Quindi stampa nuovamente quando il numero di riga corrente è 4 in più di quello stampato in precedenza.


0
awk 'c&&!--c;/img class=\"devil_icon/{c=4};/img class=\"devil_icon/' input.txt

Stai essenzialmente facendo una ricerca e sostituzione. Puoi aggiungere solo una ricerca nello stesso comando e li stamperà entrambi :)

awk 'c&&!--c;/pattern/{c=4};/pattern/' input.txt
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.