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 deliminate) al Hvecchio spazio. Le righe non corrispondenti barvengono quindi eliminate. Sulle linee corrispondenti, lo spazio del motivo viene svuotato, xmodificato con lo spazio di attesa e la linea vuota iniziale nello spazio del motivo viene rimossa.
Con un input enorme e poche occorrenze di barquesto 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'
fooe l'ultimobare stampi tutto il resto, se non altro. Con un flusso dovresti leggere fino al primofooe bufferizzare tutte le righe successive in memoria fino a EOF, svuotando il buffer ogni volta chebarviene visto un. Ciò potrebbe significare buffering dell'intero flusso in memoria.