Wie kann ich sed verwenden, um alle Zeilen in einer Textdatei zu löschen, die eine bestimmte Zeichenfolge enthalten?
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
Es gibt viele andere Möglichkeiten, Zeilen mit einer bestimmten Zeichenfolge neben sed
zu löschen:
awk '!/pattern/' file > temp && mv temp file
Ruby -i.bak -ne 'print if not /test/' file
Perl -ni.bak -e "print unless /pattern/" file
while read -r line
do
[[ ! $line =~ pattern ]] && echo "$line"
done <file > o
mv o file
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
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.
Der einfache Weg mit GNU sed
:
sed --in-place '/some string here/d' yourfile
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 gDas 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.
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.
Um ein ortähnliches Ergebnis mit grep
zu erhalten, können Sie Folgendes tun:
echo "$(grep -v "pattern" filename)" >filename
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
Sie können dies auch verwenden:
grep -v 'pattern' filename
Hier wird -v
nur ein anderes als Ihr Muster gedruckt (dh Übereinstimmung invertieren).
echo -e "/thing_to_delete\ndd\033:x\n" | vim file_to_edit.txt
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).
cat filename | grep -v "pattern" > filename.1
mv filename.1 filename
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