2009-11-03 21 views
62

¿Cómo puedo hacer que las líneas coincidan con sed según alguna expresión, pero ignore las líneas que no coinciden, en lugar de dejarlas imprimir?Have sed ignore las líneas que no coinciden

Como un ejemplo real, quiero correr scalac (el compilador Scala) en un conjunto de archivos, y leer desde su salida -verbose.class los archivos creados. scalac -verbose genera un montón de mensajes, pero solo nos interesan los del formulario [wrote some-class-name.class]. Lo que estoy haciendo actualmente está presente (es |& manera fiesta de 4.0 a stderr tubería para el próximo programa):

$ scalac -verbose some-file.scala ... |& sed 's/^\[wrote \(.*\.class\)\]$/\1/' 

Esto extraerá los nombres de archivo de los mensajes que nos interesan, pero lo hará ¡también permita que todos los otros mensajes pasen sin cambios! Por supuesto, podríamos hacer en su lugar esto:

$ scalac -verbose some-file.scala ... |& grep '^\[wrote .*\.class\]$' | 
    sed 's/^\[wrote \(.*\.class\)\]$/\1/' 

que funciona, pero se parece mucho a dar la vuelta al problema real, que es cómo instruir sed hacer caso omiso de las líneas no coincidentes desde la entrada. ¿Entonces cómo hacemos eso?

Respuesta

65

Otra forma con llanura sed:

sed -e 's/.../.../;t;d' 

s/// es una substituion, t sin ninguna etiqueta condicionalmente salta todos los siguientes comandos, d elimina línea.

No hay necesidad de perl o grep.

(editado después de la sugerencia de Nicholas Riley)

+3

En OS X 10.8.2 tuve que separar 'tx' y' d' con una línea nueva en lugar de un punto y coma, ya que estaba obteniendo la etiqueta 'no definida 'x; d;: x''. – davidchambers

+4

Mejor aún: 'sed-e 's /.../.../' -e 'tx' -e 'd' -e ': x'' (sugerido en un comentario sobre una [pregunta similar] (http : //stackoverflow.com/a/1252191/312785)). – davidchambers

+1

't' se transferirá al final de la secuencia de comandos si no se proporciona ninguna etiqueta, por lo tanto más simple: 'sed-e 's /.../.../' -e 't' -e 'd''. –

3

Uso Perl:

... |& perl -ne 'print "$1\n" if /^\[wrote (.*\.class)\]$/' 
164

Si no desea imprimir líneas que no coinciden, puede utilizar la combinación de

  • -n opción, que indica a sed que no imprima
  • p indicador que le indica a sed que muestre lo que se corresponde

Esto da:

sed -n 's/.../.../p' 
+7

Esta debe ser la respuesta aceptada –

+1

Una desventaja de este enfoque es que si usted tiene múltiples expresiones que coinciden, el resultado también será impreso en múltiples ocasiones. Por ejemplo: 'echo foo | sed -n-e 's/foo/bar/p' -e 's/bar/oof/p'' generará tanto 'bar' como' oof' en líneas separadas. Aunque la variedad de etiquetas no puede manejar múltiples patrones, ya que eliminará la línea si el primer patrón no coincide. – Rapsey

Cuestiones relacionadas