it-swarm-eu.dev

Elimina le righe in un file di testo che contiene una stringa specifica

Come utilizzerei sed per cancellare tutte le righe in un file di testo che contiene una stringa specifica?

1461

Per rimuovere la linea e stampare l'output su standard:

sed '/pattern to match/d' ./infile

Per modificare direttamente il file:

sed -i '/pattern to match/d' ./infile

Per modificare direttamente il file (e creare un backup):

sed -i.bak '/pattern to match/d' ./infile

Per utenti Mac OS X e FreeBSD:

sed -i '' '/pattern/d' ./infile
2251
SiegeX

Esistono molti altri modi per eliminare le righe con una stringa specifica oltre a sed:

AWK

awk '!/pattern/' file > temp && mv temp file

Ruby (1.9+)

Ruby -i.bak -ne 'print if not /test/' file

Perl

Perl -ni.bak -e "print unless /pattern/" file

Shell (bash 3.2 e successive)

while read -r line
do
  [[ ! $line =~ pattern ]] && echo "$line"
done <file > o
mv o file

GNU grep

grep -v "pattern" file > temp && mv temp file

E ovviamente sed (stampare l'inverso è più veloce dell'effettiva cancellazione):

sed -n '/pattern/!p' file
568
kurumi

Puoi usare sed per sostituire le linee in posizione in un file. Tuttavia, sembra essere molto più lento rispetto all'utilizzo di grep per l'inverso in un secondo file e quindi lo spostamento del secondo file sull'originale.

per esempio.

sed -i '/pattern/d' filename      

o

grep -v "pattern" filename > filename2; mv filename2 filename

Il primo comando richiede comunque 3 volte di più sulla mia macchina.

204
slashdottir

Il modo semplice per farlo, con GNU sed:

sed --in-place '/some string here/d' yourfile
58
Kevin Nguyen

Puoi prendere in considerazione l'utilizzo di ex (che è un editor basato su comandi Unix standard):

ex +g/match/d -cwq file

dove:

  • + esegue il comando Ex dato (man ex), come -c che esegue wq (scrivi e chiudi)
  • g/match/d - Ex comando per cancellare le righe con match, vedi: Power of g

L'esempio precedente è un metodo conforme a POSIX per la modifica diretta di un file secondo questo post a Unix.SE e specifiche POSIX per ex .


La differenza con sed è che:

sed è un S tream ED itor, non un editor di file.BashFAQ

A meno che non ti piaccia codice inopportuno, sovraccarico I/O e altri effetti collaterali negativi. Quindi in pratica alcuni parametri (come in-place/-i) sono estensioni FreeBSD non standard e potrebbero non essere disponibili su altri sistemi operativi.

27
kenorb

Ero alle prese con questo su Mac. Inoltre, avevo bisogno di farlo usando la sostituzione variabile.

Quindi ho usato:

sed -i '' "/$pattern/d" $file

dove $file è il file in cui è necessaria l'eliminazione e $pattern è il modello da abbinare per la cancellazione.

Ho scelto '' da questo commento .

La cosa da notare qui è l'uso di doppie virgolette in "/$pattern/d". La variabile non funzionerà quando usiamo le virgolette singole.

13
Aniket Sinha

Per ottenere un risultato simile come grep puoi farlo:

echo "$(grep -v "pattern" filename)" >filename
12
Jahid

Ho fatto un piccolo benchmark con un file che contiene circa 345.000 linee. In questo caso, il modo con grep sembra essere circa 15 volte più veloce rispetto al metodo sed.

Ho provato entrambi con e senza l'impostazione LC_ALL = C, non sembra cambiare significativamente i tempi. La stringa di ricerca (CDGA_00004.pdbqt.gz.tar) è da qualche parte nel mezzo del file.

Ecco i comandi e i tempi:

time sed -i "/CDGA_00004.pdbqt.gz.tar/d" /tmp/input.txt

real    0m0.711s
user    0m0.179s
sys     0m0.530s

time Perl -ni -e 'print unless /CDGA_00004.pdbqt.gz.tar/' /tmp/input.txt

real    0m0.105s
user    0m0.088s
sys     0m0.016s

time (grep -v CDGA_00004.pdbqt.gz.tar /tmp/input.txt > /tmp/input.tmp; mv /tmp/input.tmp /tmp/input.txt )

real    0m0.046s
user    0m0.014s
sys     0m0.019s
11
Jadzia

Puoi anche usare questo:

 grep -v 'pattern' filename

Qui -v stamperà solo altro che il tuo pattern (che significa invert match).

9
Bhuvanesh
8
Oleg Mazko

echo -e "/thing_to_delete\ndd\033:x\n" | vim file_to_edit.txt

2
Shizzmo
Perl -i    -nle'/regexp/||print' file1 file2 file3
Perl -i.bk -nle'/regexp/||print' file1 file2 file3

Il primo comando modifica il file (s) inplace (-i).

Il secondo comando fa la stessa cosa ma conserva una copia o un backup dei file originali aggiungendo .bk ai nomi dei file (.bk può essere cambiato in qualsiasi cosa).

2
Kjetil S.
cat filename | grep -v "pattern" > filename.1
mv filename.1 filename
0
Andrey Izman

Nel caso in cui qualcuno volesse farlo per le corrispondenze esatte delle stringhe, puoi usare il flag -w in grep -w per intero. Cioè, per esempio se vuoi cancellare le linee che hanno il numero 11, ma mantieni le linee con il numero 111:

-bash-4.1$ head file
1
11
111

-bash-4.1$ grep -v "11" file
1

-bash-4.1$ grep -w -v "11" file
1
111

Funziona anche con il flag -f se vuoi escludere più pattern esatti contemporaneamente. Se "lista nera" è un file con più motivi su ciascuna riga che si desidera eliminare da "file":

grep -w -v -f blacklist file
0
FatihSarigol