Come trovare le linee che corrispondono a un modello ed eliminarle?


14

In un file con molte righe voglio eliminare le righe che iniziano con HERE IT IS.

Come posso farlo usando solo gli strumenti da riga di comando?


2
Anche se un po 'non convenzionale, potresti usare vimcosì vim '+g/^HERE IT IS/d' +wq test.txt
:;

@Doorknob, grazie per averlo sottolineato. In realtà sto per usare vim
micgeronimo il

Risposte:


28

Prova sed:

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

ATTENZIONE: è meglio eseguire un backup quando si utilizza -iswitch di sed:

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

Il file originale rimarrà come <file>.bake il file modificato sarà <file>.


Come posso inserire il carattere di nuova riga dopo la stringa corrispondente e scrivere su una nuova riga?
micgeronimo,

2
sed -i 's/^HERE IT IS/HERE IT IS\n/' <file>
Hememl

1
@micgeronimo: felice di aiutarti. Controlla le mie modifiche per favore.
Hememl

6
@micgeronimo prova a porre la domanda a cui vuoi veramente rispondere nella tua domanda originale (ricorda che puoi modificarla), piuttosto che attraverso commenti che potrebbero essere ripuliti / eliminati. È possibile utilizzare sed '/^HERE IT IS/G' file.
Steeldriver,

1
L'uso di Sed è così professionale.
Lakshya,

18

Oltre all'ottimo grepe sedalle risposte che hai ricevuto, ecco alcuni altri strumenti che possono fare la stessa cosa:

  • Alcuni modi 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
    

    È possibile aggiungere l' -iopzione a uno qualsiasi degli esempi per modificare il file in atto:

    perl -i.bak -ne '/^HERE IT IS/ || print' file        
    
  • (G) awk

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

    Le versioni più recenti (4.1.1 e successive) di GNU awk(impostazione predefinita awksu Linux) possono anche modificare il file in atto:

    gawk -i inplace  '!/^HERE IT IS/' file
    
  • Shell ( bash, zsh, ksh, probabilmente altri). Questo è un po 'sciocco, può essere fatto, ma altri strumenti sono migliori.

    while IFS= read -r line; do 
      [[ $line =~ ^"HERE IT IS" ]] || printf "%s\n" "$line"
    done < file > newfile
    

1
Ti stai solo mettendo in mostra! ;-) (ma hai ottenuto un voto, perché è intelligente e ho imparato molto e bashquello mi ha fatto LOL)
Fabby

quello bash dovrebbe usare printf "%s\n" "$line": quotando $ line per preservare gli spazi bianchi, ed evitando alcuni problemi di eco (interpretando caratteri speciali, ecc.). ed evita anche la necessità di aggiungere --.
Olivier Dulac,

@OlivierDulac abbastanza giusto. Non volevo complicare le cose per i casi marginali, ma dal momento che Cuanglm ha aggiunto IFS=e -r, potrei anche andare fino in fondo e renderlo robusto.
terdon,

@terdon: è tutto per il bene migliore ^^ (e ho già fatto +1, tuttavia, dato che è molto informativo per i principianti)
Olivier Dulac,

2
@OlivierDulac Ti posso assicurare che se avessi pubblicato su Unix e Linux avrei usato printf, IFS =, -r e quoting :). Spesso semplifico le cose per il pubblico australiano che spesso si sente a disagio con la riga di comando.
terdon,

13

Vorrei usarli grepper filtrarli. Per esempio :

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

Quindi sposta il file indietro per tornare al file.


Pensiero intelligente
Anwar,

5

sed è sicuramente la strada da percorrere.

Questa leggera modifica del comando fornito da @heemayl eliminerà la riga indipendentemente dal fatto che lo stesso caso venga utilizzato nel modello o meno, a causa di I nel riferimento del modello.

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

Se avessi diversi file in una directory su cui volevi farlo, potresti combinarli con find in questo modo.

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

L'opzione maxdepth significa che questo non verrà utilizzato nelle directory.


4

Un'altra opzione Python:

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

Dove f è il percorso del file, tra virgolette.


4

grep

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

(?!HERE IT IS)asserzione lookahead negativa che fa corrispondere al motore regex tutto il limite iniziale della linea ( che di solito è abbinato^ ) solo se non è seguito dalla stringaHERE IT IS

pitone

#!/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="")

Salvare lo script in un file, dire script.pye quindi eseguirlo tramite il comando seguente sul terminale.

python3 script.py infile

potresti usare regex lì, tipo [print(l, end = "") for l in open(fil).readlines() if not re.match("HERE IT IS", l)], ma non è molto più efficiente di startswith. Mi chiedevo come [print(l, end = "") for l in open(f).readlines() if not l.startswith("HERE IT IS")]non produrre l'output in un elenco.
Avinash Raj,

La prima volta che mi sono imbattuto, mi è sembrato strano. Genera un comando di stampa (o qualsiasi azione tu voglia fare con esso) per tutti gli elementi nell'elenco definito.
Jacob Vlijm,

Deselezionandolo, solo per divertimento :)
Jacob Vlijm,

1

Puoi usare Vim in modalità Ex:

ex -sc 'g/^HERE IT IS/d' -cx file
  1. g ricerca globale

  2. d Elimina

  3. x salva e chiudi

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.