it-swarm.com.de

Löschen Sie Zeilen in einer Textdatei, die eine bestimmte Zeichenfolge enthalten

Wie kann ich sed verwenden, um alle Zeilen in einer Textdatei zu löschen, die eine bestimmte Zeichenfolge enthalten?

1461

So entfernen Sie die Zeile und drucken die Ausgabe als Standard aus:

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

So ändern Sie die Datei direkt:

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

So ändern Sie die Datei direkt (und erstellen Sie eine Sicherung):

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

Für Benutzer von Mac OS X und FreeBSD:

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

Es gibt viele andere Möglichkeiten, Zeilen mit einer bestimmten Zeichenfolge neben sed zu löschen:

AWK

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

Rubin (1.9+)

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

Perl

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

Shell (Bash 3.2 und höher)

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

Und natürlich sed (das Drucken der Inversen ist schneller als das Löschen):

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

Sie können sed verwenden, um Zeilen in einer Datei zu ersetzen. Es scheint jedoch viel langsamer als die Verwendung von grep für die Umkehrung in eine zweite Datei und das Verschieben der zweiten Datei über das Original.

z.B.

sed -i '/pattern/d' filename      

oder

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

Der erste Befehl dauert auf meiner Maschine trotzdem dreimal länger.

204
slashdottir

Der einfache Weg mit GNU sed:

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

Sie können die Verwendung von ex (einem standardmäßigen, auf Unix-Befehlen basierenden Editor) in Betracht ziehen:

ex +g/match/d -cwq file

woher:

  • + führt den angegebenen Ex-Befehl (man ex) aus, genauso wie -c, der wq (Schreiben und Beenden) ausführt.
  • g/match/d - Ex-Befehl zum Löschen von Zeilen mit der angegebenen match, siehe: Power of g

Das obige Beispiel ist eine POSIX-kompatible Methode für die direkte Bearbeitung einer Datei nach diesem post bei Unix.SE und POSIX-Spezifikationen für ex .


Der Unterschied zu sed ist folgender:

sed ist ein S tream ED itor, kein Datei-Editor.BashFAQ

Es sei denn, Sie genießen nicht portierbaren Code, E/A-Overhead und andere schlechte Nebenwirkungen. Grundsätzlich sind einige Parameter (wie in-place/-i) nicht standardmäßige FreeBSD-Erweiterungen und möglicherweise nicht für andere Betriebssysteme verfügbar.

27
kenorb

Ich hatte Probleme damit auf dem Mac. Außerdem musste ich das Ersetzen von Variablen durchführen.

Also habe ich benutzt:

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

dabei ist $file die Datei, in der eine Löschung erforderlich ist, und $pattern ist das Muster, das zum Löschen abgeglichen werden soll.

Ich habe den '' aus diesem Kommentar ausgewählt.

Zu beachten ist hier die Verwendung von Anführungszeichen in "/$pattern/d". Variable funktioniert nicht, wenn wir einfache Anführungszeichen verwenden.

13
Aniket Sinha

Um ein ortähnliches Ergebnis mit grep zu erhalten, können Sie Folgendes tun:

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

Ich habe einen kleinen Benchmark mit einer Datei erstellt, die ungefähr 345 000 Zeilen enthält. Die Methode mit grep scheint in diesem Fall etwa 15-mal schneller als die sed-Methode zu sein.

Ich habe sowohl mit als auch ohne die Einstellung LC_ALL = C ausprobiert, es scheint die Timings nicht wesentlich zu ändern. Die Suchzeichenfolge (CDGA_00004.pdbqt.gz.tar) befindet sich irgendwo in der Mitte der Datei.

Hier sind die Befehle und die Timings:

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

Sie können dies auch verwenden:

 grep -v 'pattern' filename

Hier wird -v nur ein anderes als Ihr Muster gedruckt (dh Übereinstimmung invertieren).

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

Der erste Befehl bearbeitet die Datei (en) inplace (-i).

Der zweite Befehl führt dasselbe aus, behält jedoch eine Kopie oder Sicherung der ursprünglichen Datei (en) bei, indem er den Dateinamen .bk hinzufügt (.bk kann in irgendetwas geändert werden).

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

Für den Fall, dass jemand dies für exakte Übereinstimmungen von Strings tun möchte, können Sie das Flag -w in grep - w für das Ganze verwenden. Das ist zum Beispiel, wenn Sie die Zeilen mit der Nummer 11 löschen möchten, aber die Zeilen mit der Nummer 111 beibehalten:

-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

Es funktioniert auch mit dem Flag -f, wenn Sie mehrere exakte Muster gleichzeitig ausschließen möchten. Wenn "Blacklist" eine Datei mit mehreren Mustern in jeder Zeile ist, die Sie aus "Datei" löschen möchten:

grep -w -v -f blacklist file
0
FatihSarigol