Tengo el siguiente código que eliminará líneas con el patrón bananay 2 líneas después:
sed '/banana/I,+2 d' file
¡Hasta aquí todo bien! Pero lo necesito para eliminar 2 líneas antes banana , pero no puedo obtenerlo con un "signo menos" o lo que sea (similar a lo que grep -v -B2 banana filedebería hacer, pero no lo hace):
teresaejunior@localhost ~ > LC_ALL=C sed '-2,/banana/I d' file
sed: invalid option -- '2'
teresaejunior@localhost ~ > LC_ALL=C sed '/banana/I,-2 d' file
sed: -e expression #1, char 16: unexpected `,'
teresaejunior@localhost ~ > LC_ALL=C sed '/banana/I,2- d' file
sed: -e expression #1, char 17: unknown command: `-'
shell-script
text-processing
sed
awk
Teresa e Junior
fuente
fuente

awk '{l[m=NR]=$0}/banana/{for(i=NR-2;i<=NR;i++)delete l[i]}END{for(i=1;i<=m;i++)if(i in l)print l[i]}'. Esto no es eficiente, así que esto es solo una pista, no una solución.tac file | sed ... | tac. : Psed '/banana/,+2d' fileeso también funcionaráawk 'tolower($0)~/bandana/{print prev[!idx];print prev[idx]} {idx=!idx;prev[idx]=$0}' fileindado que este es un comentario y no una respuesta (ya hay otras respuestas), no entraré en demasiados detalles, pero el quid de la cuestión es que siempre tiene la dos registros anteriores en Anterior [0] y anterior [1], el "más fresco", según la iteración pero siempre enprev[idx], por lo que cuando se imprime, se imprimen en!idxentoncesidxorden. En cualquier caso, alterneidxy coloque el registro actualprev[idx].Respuestas:
Sed no retrocede: una vez que se procesa una línea, se hace. Por lo tanto, "buscar una línea e imprimir las N líneas anteriores" no funcionará como está, a diferencia de "encontrar una línea e imprimir las siguientes N líneas", que es fácil de injertar.
Si el archivo no es demasiado largo, ya que parece estar bien con las extensiones GNU, puede usarlo
tacpara invertir las líneas del archivo.Otro ángulo de ataque es mantener una ventana deslizante en una herramienta como awk. Adaptación de ¿Hay alguna alternativa a los interruptores grep's -A -B -C (para imprimir algunas líneas antes y después)? (advertencia: mínimamente probado):
Uso:
/path/to/script -v pattern='banana' -v before=2fuente
sedtambién puede hacer ventanas deslizantes, pero el script resultante es típicamente tan ilegible que es más fácil de usarawk.awkguión no es del todo correcto; as-is imprime líneas en blanco y pierde las últimas líneas. Esto parece solucionarlo, pero puede no ser ideal o correcto en sí:if (NR-before in h) { print...; delete...; }... y en laENDsección:for (i in h) print h[i]... Además, el script awk imprime la línea correspondiente, pero latac/secversión no; pero la pregunta es un poco ambigua en esto ... El script awk "original", al que proporcionó un enlace, funciona bien ... Me gusta ... No estoy seguro de cómo el 'mod' anterior afecta la impresión después de líneas ...Esto es bastante fácil con ex o vim -e
La expresión dice: por cada línea que contenga banana en el rango de la línea actual -2 a la línea actual, elimine.
Lo bueno es que el rango también puede contener búsquedas hacia adelante y hacia atrás, por ejemplo, esto eliminará todas las secciones del archivo que comienzan con una línea que contiene manzana y termina con una línea que contiene naranja y una línea con plátano:
fuente
Usando la "ventana deslizante" en
perl:fuente
Puede hacer esto de manera bastante simple con
sed:No sé por qué alguien diría lo contrario, pero para encontrar una línea e imprimir líneas anteriores se
sedincorpora laPprimitiva\nrint incorporada que escribe solo hasta el primer carácter de línea ewline en el espacio del patrón. LaDprimitiva elete complementaria elimina ese mismo segmento de espacio de patrón antes de reciclar recursivamente el script con lo que queda. Y para redondearlo, hay una primitiva para agregar laNlínea de entrada ext al espacio de patrón después de un\ncarácter de línea e insertado .Para que esa línea de
sedsea todo lo que necesita. Simplemente lo reemplazasmatchcon lo que sea tu expresión regular y eres dorado. Esa también debería ser una solución muy rápida .Tenga en cuenta también que contará correctamente un
matchprecedente inmediatomatchcomo un disparador para silenciar la salida de las dos líneas anteriores y también silenciará su impresión:Para que funcione para un número arbitrario de líneas, todo lo que necesita hacer es obtener una pista.
Asi que:
... elimina las 5 líneas que preceden a cualquier coincidencia.
fuente
Utilizando
man 1 ed:fuente