Ecco un altro modo con sed
:
sed '/foo/,$!d;H;/bar/!d;s/.*//;x;s/\n//' infile
Aggiunge ogni riga /foo/,$
nell'intervallo (le righe !
non comprese in questo intervallo vengono d
eliminate) al H
vecchio spazio. Le righe non corrispondenti bar
vengono quindi eliminate. Sulle linee corrispondenti, lo spazio del motivo viene svuotato, x
modificato con lo spazio di attesa e la linea vuota iniziale nello spazio del motivo viene rimossa.
Con un input enorme e poche occorrenze di bar
questo dovrebbe essere (molto) più veloce che trascinare ogni linea nello spazio del pattern e poi, ogni volta, controllare lo spazio del pattern per bar
.
Ha spiegato:
sed '/foo/,$!d # delete line if not in this range
H # append to hold space
/bar/!d # if it doesn't match bar, delete
s/.*// # otherwise empty pattern space and
x # exchange hold buffer w. pattern space then
s/\n// # remove the leading newline
' infile
Certo, se questo è un file (e si adatta alla memoria) potresti semplicemente eseguire:
ed -s infile<<'IN'
.t.
/foo/,?bar?p
q
IN
perché ed
può cercare avanti e indietro.
È anche possibile leggere un output del comando nel buffer di testo se la shell supporta la sostituzione di processo:
printf '%s\n' .t. /foo/,?bar?p q | ed -s <(your command)
o in caso contrario, con gnu ed
:
printf '%s\n' .t. /foo/,?bar?p q | ed -s '!your command'
foo
e l'ultimobar
e stampi tutto il resto, se non altro. Con un flusso dovresti leggere fino al primofoo
e bufferizzare tutte le righe successive in memoria fino a EOF, svuotando il buffer ogni volta chebar
viene visto un. Ciò potrebbe significare buffering dell'intero flusso in memoria.