Elimine la línea que contiene cierta cadena y la siguiente línea

Yo uso esto

cat foo.txt | sed "/bar/d"

para eliminar las líneas que contienen la cadena bar en el archivo.

Sin embargo, me gustaría eliminar esas líneas y la línea directamente después . Preferiblemente en sed, awk u otra herramienta que esté disponible en MinGW32.

Es una especie de reverso de lo que puedo obtener en grep con -A y -B para imprimir también líneas coincidentes como líneas antes / después de la línea coincidente.

¿Hay alguna manera fácil de lograrlo?

Comentarios

  • Solo para información: estoy ‘ analizando registros cuyas entradas son de dos líneas. Así que quiero encontrar una entrada que coincida con el patrón y eliminarla, así como la siguiente línea. Por lo tanto, no ‘ necesito manejar líneas de coincidencia consecutivas, ¡pero gracias de todos modos por la integridad de sus respuestas!

Responder

Si tiene GNU sed (es decir, Linux no integrado o Cygwin):

sed "/bar/,+1 d" 

Si tener bar en dos líneas consecutivas, esto eliminará la segunda línea sin analizarla. Por ejemplo, si tiene un archivo de 3 líneas bar / bar / foo, la línea foo permanecerá.

Comentarios

  • +1 para la longitud 🙂 En mi particular ejemplo, no ‘ t tengo bar consecutivos, por lo que este es muy fácil de recordar.
  • sed '/bar/d' si solo desea » Eliminar la línea que contiene cierta cadena » y no el siguiente.
  • Si quiero eliminar todas las líneas después de las matemáticas, ¿entonces?
  • @Pandya Eso ‘ es diferente. Puede utilizar, por ejemplo, sed '/math/q'
  • @ A.K. Si solo desea eliminar la línea coincidente, ‘ es aún más simple: sed '/bar/d'

Respuesta

Si bar puede aparecer en líneas consecutivas, puede hacer:

awk "/bar/{n=2}; n {n--; next}; 1" < infile > outfile 

que se puede adaptar para eliminar más de 2 líneas cambiando las 2 anteriores por el número de líneas a eliminar, incluida la correspondiente.

Si no es así, «se hace fácilmente en sed con la solución @MichaelRollins» o:

sed "/bar/,/^/d" < infile > outfile 

Comentarios

  • La otra ventaja de la solución AWK es que puedo reemplazar /bar/ con /bar|baz|whatever/. En sed esa sintaxis no ‘ parece funcionar.
  • @ jakub.g, tengo GNU sed ( v4.4 ahora). No estoy seguro de los demás. Lo que sé es que utiliza la sintaxis de expresión regular » básica » de forma predeterminada. >

t trabajo. Para lograr lo que desea, puede poner una barra invertida delante de cada línea vertical o puede pedirle asedque use » extendido » expresiones regulares. Más información aquí: gnu.org/software/sed/manual/html_node/…

. Tenga en cuenta que esto también se aplica agrep. Aquí ‘ es mi propio ejemplo de trabajo:echo $'0a\n1b\n2c' | sed '/0a\|1b/d'.

Responder

No hablo sed con fluidez, pero es fácil hacerlo en awk:

awk "/bar/{getline;next} 1" foo.txt 

El El script awk dice: para una línea que contiene bar, obtenga la siguiente línea (getline), luego omita todo el procesamiento posterior (siguiente). El patrón 1 al final imprime las líneas restantes.

Actualización

Como se señaló en el comentario, la solución anterior no funcionó con bar. Aquí hay una solución revisada, que la tiene en cuenta:

awk "/bar/ {while (/bar/ && getline>0) ; next} 1" foo.txt 

Ahora seguimos leyendo para omitir todas las líneas / bar /.

Comentarios

  • Para replicar grep -A 100%, también debes manejar cualquier número de líneas correctamente (eliminando todo el bloque y 1 línea después).

Responder

Querrá hacer uso de las capacidades de secuencias de comandos de sed «para lograr esto.

$ sed -e "/bar/ { $!N d }" sample1.txt 

Datos de muestra:

$ cat sample1.txt foo bar biz baz buz 

El comando «N» agrega la siguiente línea de entrada en el espacio del patrón. Esto combinado con la línea de la coincidencia del patrón (/ barra /) serán las líneas que desea eliminar. Luego puede eliminar normalmente con el comando «d».

Comentarios

  • ¿Cómo escribo una nueva línea en la consola? ¿O es solo un script?
  • @ jakub.g: con GNU sed: sed -e '/bar/{N;d}' sample1.txt

Respuesta

Si alguna línea inmediatamente después de una coincidencia debe eliminarse, su programa sed tendrá que considerar coincidencias consecutivas. En otras palabras, si elimina una línea después de una coincidencia que también coincide, probablemente debería eliminar la línea que sigue a esa también.

Está implementado de manera bastante simple, pero debe mirar hacia atrás un poco. .

printf %s\\n 0 match 2 match match \ 5 6 match match match \ 10 11 12 match 14 15 | sed -ne"x;/match/!{g;//!p;}" 

 0 6 11 12 15  

Funciona intercambiando espacios de retención y patrón para cada línea leída, por lo que la última línea se puede comparar con la actual cada vez. Entonces, cuando sed lee una línea, intercambia el contenido de sus búferes, y la línea anterior es el contenido de su búfer de edición, mientras que la línea actual se coloca en el espacio de espera.

Entonces sed busca en la línea anterior una coincidencia con match , y si su ! no se encuentran las dos expresiones en la { función } se ejecutan. sed g establecerá el espacio de retención sobrescribiendo el espacio de patrón, lo que significa que la línea actual estará en ambos espacios de retención y de patrón. y luego // comprobará si coincide con su expresión regular compilada más recientemente – match – y si no match es p impreso.

Esto significa que una línea solo se imprime si no match y la línea inmediatamente anterior no match . También evita intercambios innecesarios por secuencias de match es.

Si desea una versión que pueda eliminar un número arbitrario de líneas que ocurre después de un match necesitaría un poco más de trabajo:

printf %s\\n 1 2 3 4 match \ match match 8 \ 9 10 11 12 13 \ 14 match match \ 17 18 19 20 21 | sed -net -e"/match/{h;n;//h;//!H;G;s/\n/&/5;D;}" -ep 

. .. reemplace el 5 con el número de líneas (incluida la línea coincidente) que le gustaría eliminar …


1 2 3 4 12 13 14 21 

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *