Aquí hay otra forma con sed
:
sed '/foo/,$!d;H;/bar/!d;s/.*//;x;s/\n//' infile
Agrega cada línea en el /foo/,$
rango ( !
se d
eligen líneas que no están en este rango ) al H
espacio antiguo. Las líneas que no coinciden bar
se eliminan. En las líneas que coinciden, el espacio del patrón se vacía, se x
cambia con el espacio de espera y se elimina la línea vacía principal en el espacio del patrón.
Con una entrada enorme y pocas ocurrencias de bar
esto, debería ser (mucho) más rápido que tirar de cada línea al espacio del patrón y luego, cada vez, verificar el espacio del patrón bar
.
Explicado:
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
Claro, si este es un archivo (y cabe en la memoria) simplemente podría ejecutar:
ed -s infile<<'IN'
.t.
/foo/,?bar?p
q
IN
porque ed
puede buscar hacia adelante y hacia atrás.
Incluso podría leer una salida de comando en el búfer de texto si su shell admite la sustitución de procesos:
printf '%s\n' .t. /foo/,?bar?p q | ed -s <(your command)
o si no es así, con gnu ed
:
printf '%s\n' .t. /foo/,?bar?p q | ed -s '!your command'
foo
y el últimobar
e imprimirá todo en el medio, si acaso. Con un flujo, tendría que leer hasta el primerofoo
, y almacenar en el búfer todas las líneas subsiguientes en la memoria hasta EOF, vaciando el búfer cada vez quebar
se ve a. Esto podría significar almacenar en búfer todo el flujo en la memoria.