Eliminar líneas que no comienzan con un patrón de un conjunto de patrones dado

10

Tengo un archivo que contiene datos como este:

report aaaaaaaa  
-  ..  
-th bbbbbbbbb  
-to ccccccccc

.. --.

Pregunta: Quiero eliminar cualquier línea que no comience con las siguientes cadenas:

report  
-th  
-to

eso significa que el resultado deseado eliminará todos los puntos y hashes no deseados del medio y se verá así:

report aaaaaaaa  
-th bbbbbbbbb  
-to ccccccccc

sed/ awk/ grep/ etc cualquier solución que funcione.

Rana Khan
fuente

Respuestas:

15

Utilizando sedpara modificar el archivo en su lugar:

sed -i '/^\(report\|-t\(h\|o\)\)/!d' your_file

Esto le indica sedque elimine todas las líneas que no coinciden con el patrón. El patrón en sí es ^(inicio de línea), seguido de uno reporto -tseguido de uno ho o.

Debe tener en cuenta que esto no es una modificación real en el lugar: sedcrea una copia de seguridad temporal y sobrescribe el archivo original con ella.

Si desea sedconservar una copia de respaldo del archivo original (lo que podría ser una buena idea si el archivo contiene datos críticos), otorgue al -iconmutador una extensión para crear un archivo de respaldo:

sed -i'.bak' -e '/^\(report\|-t\(h\|o\)\)/!d' your_file

modificará your_filey creará una copia de seguridad del original llamado your_file.bak.

Una nota al margen

No malinterpretes mis intenciones ni te ofendas por esto, pero he notado que tienes muchas preguntas similares relacionadas con el procesamiento de texto y expresiones regulares. Te aconsejo que empezar a aprender sed, awky greppor su cuenta para ayudar a acelerar su productividad. Nuevamente, no me malinterpreten, estoy muy feliz de ayudar (como la mayoría de las personas por aquí); es solo que creo que puede beneficiarse enormemente al recoger estas herramientas para su uso diario.

Solo para demostrar lo útil que es la gente por aquí, considere la sugerencia de @ slm en los comentarios a continuación y siéntase libre de visitar esta sala de chat en cualquier momento para preguntas.

Joseph R.
fuente
1
Su expresión regular parece innecesariamente críptica. Creo que en realidad usas más caracteres que si hubieras enumerado las tres opciones explícitamente.
nispio
1
@nispio Lo sé, pero es probable que sea más eficiente si el archivo en cuestión es grande.
Joseph R.
Interesante. Siempre he medido expresiones regulares en términos de longitud o legibilidad. Nunca he pensado mucho en la velocidad de ejecución. No creo saber lo suficiente sobre cómo se evalúan para juzgar qué es rápido, pero supongo que también es específico de la implementación, ¿verdad?
nispio
3
Reiterando lo que dijo Joseph sobre estar dispuesto a ayudar, si tiene preguntas generales que no encajan en el estilo de Preguntas y Respuestas, siempre puede intentar conversar con nosotros en la sala de chat de este sitio. chat.stackexchange.com/rooms/26/unix-and-linux . Varios de nosotros vivimos allí 8-)
slm
@slm Gracias por esto. Lo agregaré a mi respuesta.
Joseph R.
10

Puede usar grep simple para esto:

$ grep -e '^report\|^-th\|^-to' filename
Pradeepchhetri
fuente
1
No es un gran ahorro, pero puede combinar el -th/ -toen -t[ho].
Kevin
grep -eoegrep
Olivier Dulac el
2

Utilizando sed:

sed -n -e '/^report\|^-th\|^-to/p' filename
nispio
fuente
No es un gran ahorro, pero puede combinar el -th/ -toen -t[ho].
Kevin
1
@ Kevin Eso es cierto. Vea mi conversación con Joseph R. en los comentarios a su respuesta.
nispio
2

Utilizando awk:

awk '/^report|^-t[ho]/' file
jasonwryan
fuente
No es un gran ahorro, pero puede combinar el -th/ -toen -t[ho].
Kevin
1

El interlocutor ha hecho dos puntos:

  • querer eliminar cualquier línea que no comience con "informe" o "-th" o "-to".
  • la salida deseada debería eliminar "todos esos puntos y hashes medios no deseados (sic)"

Las soluciones, en este momento, abordan el primer punto y, por lo tanto, también el segundo. Pero supongamos que el archivo es más grande y se ve así:

report aaaaaaaa  
-  ..  
-th bbbbbbbbb  
-to ccccccccc
anything else
.. --.
-tp ddd
-tq eee
     -  -----

¿No sería necesario abordar el segundo punto de OP?

sed -r -i.bak '/^[ |.|-]*$/d' input-file 

hace el trabajo de eliminar líneas presumiblemente no deseadas que contienen solo espacios, puntos y rayas y retener el resto, sea lo que sea.
Creo que el riesgo de cualquiera de los enfoques es que la naturaleza del archivo no está definida correctamente.


fuente
0

Usando Perl:

perl -ne 'print if /^report|^-t[ho]/' filename > newfile

o, para editar en el lugar (como sed, perltambién hará una copia de seguridad temporal, por lo que esto no es cierto en la edición en el lugar ):

perl -i.bak -ne 'print if /^report|^-t[ho]/' filename

Eso hará una copia del archivo original llamado filename.baky sobrescribirá su archivo original con la versión editada.

terdon
fuente