¿Cómo encontrar líneas que coincidan con un patrón y eliminarlas?

14

En un archivo con muchas líneas, quiero eliminar las líneas que comienzan con HERE IT IS.

¿Cómo puedo hacer esto usando solo herramientas de línea de comandos?

micgeronimo
fuente
2
Aunque un poco poco convencional, puede usar vimasí vim '+g/^HERE IT IS/d' +wq test.txt
:;
@Doorknob, gracias por señalar esto. En realidad estoy en camino a usar vim
micgeronimo

Respuestas:

28

Prueba sed:

sed -i '/^HERE IT IS/d' <file>

ADVERTENCIA: es mejor hacer una copia de seguridad cuando se usa el -iinterruptor de sed:

sed -i.bak '/^HERE IT IS/d' <file>

El archivo original permanecerá como <file>.baky el archivo modificado será <file>.

heemayl
fuente
¿Cómo puedo poner el carácter de nueva línea después de una cadena coincidente y escribir en nueva línea?
micgeronimo
2
sed -i 's/^HERE IT IS/HERE IT IS\n/' <file>
heemayl
1
@micgeronimo: encantado de ayudar. Mira mis ediciones por favor.
heemayl
66
@micgeronimo intente hacer la pregunta que realmente desea que se responda en su pregunta original (recuerde que puede editarla), en lugar de a través de comentarios que pueden limpiarse / eliminarse. Puedes usar sed '/^HERE IT IS/G' file.
steeldriver
1
El uso de Sed es muy profesional.
LakshyaAg
18

Además de los muy buenos grepy las sedrespuestas que ha recibido, aquí hay algunas otras herramientas que pueden hacer lo mismo:

  • Algunas formas de Perl:

    perl -ne '/^HERE IT IS/ || print' file > newfile
    perl -ne 'print if !/^HERE IT IS/' file > newfile
    perl -ne 'print unless /^HERE IT IS/' file > newfile
    

    Puede agregar el -iinterruptor a cualquiera de los ejemplos para editar el archivo en su lugar:

    perl -i.bak -ne '/^HERE IT IS/ || print' file        
    
  • (papar moscas

    awk '!/^HERE IT IS/' file > newfile
    

    Las versiones más recientes (4.1.1 y posteriores) de GNU awk(el valor predeterminado awken Linux) también pueden editar el archivo en su lugar:

    gawk -i inplace  '!/^HERE IT IS/' file
    
  • Shell ( bash, zsh, ksh, y probablemente otros). Sin embargo, esto es un poco tonto, se puede hacer, pero otras herramientas son mejores.

    while IFS= read -r line; do 
      [[ $line =~ ^"HERE IT IS" ]] || printf "%s\n" "$line"
    done < file > newfile
    
terdon
fuente
1
¡Solo estás presumiendo! ;-) (pero recibiste un voto positivo, porque es inteligente y aprendí mucho y bashme hizo LOL)
Fabby
el bash debería usarse printf "%s\n" "$line": citando $ line para preservar espacios en blanco y evitando algunos problemas de eco (interpretación de caracteres especiales, etc.). y evita la necesidad de agregar --también.
Olivier Dulac
@OlivierDulac lo suficientemente justo. No quería complicar las cosas para los casos marginales, pero dado que Cuanglm ha agregado IFS=y -r, también podría ir hasta el final y hacerlo robusto.
terdon
@terdon: todo es para el mejor bien ^^ (y ya hice +1, ya que es muy informativo para principiantes)
Olivier Dulac
2
@OlivierDulac Les puedo asegurar que si estuviera publicando en Unix y Linux , habría utilizado printf, IFS =, -r y citando :). A menudo simplifico las cosas para el público de la UA que a menudo se sienten menos cómodos con la línea de comando.
terdon
13

Solía grepfiltrarlos. Por ejemplo :

grep -v "^HERE IT IS" infile > outfile

Luego muévase de regreso al archivo.

Ben Hills
fuente
Pensamiento inteligente
Anwar
5

sed Definitivamente es el camino a seguir.

Esta ligera modificación del comando que le dio @heemayl eliminará la línea, ya sea que se use el mismo caso en el patrón o no, debido a la I en la referencia del patrón.

sed -i '/HERE IT IS/Id' <file>

Si tenía varios archivos en un directorio en el que deseaba hacer esto, podría combinarlo con buscar así.

find . -maxdepth 1 -type f -exec sed -i.bak '/HERE IT IS/Id' {} +

La opción maxdepth significa que esto no se repetirá en los directorios.

Arronico
fuente
4

Otra opción de python:

#!/usr/bin/env python3
[print(l, end = "") for l in open(f).readlines() if not l.startswith("HERE IT IS")]

Donde f es la ruta al archivo, entre comillas.

Jacob Vlijm
fuente
4

Grep

grep -P '^(?!HERE IT IS)' file

(?!HERE IT IS)aserción negativa anticipada que hace que el motor de expresiones regulares coincida con todos los límites de inicio de línea ( que generalmente coinciden^ ) solo si no es seguido por la cadenaHERE IT IS

pitón

#!/usr/bin/python3
import sys
fil = sys.argv[1]
with open(fil) as f:
    for line in f:
        if not line.startswith('HERE IT IS'):
            print(line, end="")

Guarde el script en un archivo, dígalo script.pyy luego ejecútelo a través del siguiente comando en el terminal.

python3 script.py infile
Avinash Raj
fuente
podría usar regex allí, como [print(l, end = "") for l in open(fil).readlines() if not re.match("HERE IT IS", l)], pero no es mucho más eficiente que startswith. Me preguntaba cómo [print(l, end = "") for l in open(f).readlines() if not l.startswith("HERE IT IS")]no produciría la salida en una lista.
Avinash Raj
La primera vez que me topé con él, me pareció extraño. Genera un comando de impresión (o cualquier acción que desee realizar con él) para todos los elementos de la lista definida.
Jacob Vlijm
Recuperarlo, solo por diversión :)
Jacob Vlijm
1

Puede usar Vim en modo Ex:

ex -sc 'g/^HERE IT IS/d' -cx file
  1. g búsqueda global

  2. d Eliminar

  3. x guardar y cerrar

Steven Penny
fuente