Wie würde ich sed verwenden, um alle Zeilen in einer Textdatei zu löschen, die eine bestimmte Zeichenfolge enthalten?
Wie würde ich sed verwenden, um alle Zeilen in einer Textdatei zu löschen, die eine bestimmte Zeichenfolge enthalten?
Antworten:
So entfernen Sie die Zeile und drucken die Ausgabe als Standard aus:
sed '/pattern to match/d' ./infile
So ändern Sie die Datei direkt - funktioniert nicht mit BSD sed:
sed -i '/pattern to match/d' ./infile
Gleich, aber für BSD sed (Mac OS X und FreeBSD) - funktioniert nicht mit GNU sed:
sed -i '' '/pattern to match/d' ./infile
So ändern Sie die Datei direkt (und erstellen ein Backup) - funktioniert mit BSD und GNU sed:
sed -i.bak '/pattern to match/d' ./infile
sed '/pattern to match/d' ./infile > ./newfile
oder wenn Sie eine direkte Bearbeitung durchführen möchten, können Sie das -i
Flag wie in sed hinzufügen sed -i '/pattern to match/d' ./infile
. Beachten Sie, dass die -i
Flagge GNU sed erfordert und nicht portabel ist
sed -i.backup '/pattern to match/d' ./infile
) Das hat mich mit direkten Änderungen konfrontiert.
sed
auf Dateien an, die nicht versioniert sind.
sed -i '' '/pattern/d' ./infile
.
Es gibt viele andere Möglichkeiten, Zeilen mit einer bestimmten Zeichenfolge zu löschen sed
:
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 Umkehrung ist schneller als das tatsächliche Löschen):
sed -n '/pattern/!p' file
sed
Beispiel hat ein anderes Verhalten, es greift nur! es sollte so etwas sein sed -n -i '/pattern/!p' file
.
grep -v "pattern" file > temp; mv temp file
Dies kann je nach Rückgabewert für einige der anderen Beispiele gelten.
seq -f %f 10000000 >foo.txt
. sed d: time sed -i '' '/6543210/d' foo.txt
echte 0m9.294s. sed! p: time sed -i '' -n '/6543210/!p' foo.txt
echte 0m13.671s. (Bei kleineren Dateien ist der Unterschied größer.)
Sie können sed verwenden, um Zeilen in einer Datei zu ersetzen. Es scheint jedoch viel langsamer zu sein, als grep für die Umkehrung in eine zweite Datei zu verwenden und dann die zweite Datei über das Original zu verschieben.
z.B
sed -i '/pattern/d' filename
oder
grep -v "pattern" filename > filename2; mv filename2 filename
Der erste Befehl dauert auf meinem Computer sowieso dreimal länger.
sed '/pattern/d' filename > filename2; mv filename2 filename
Der einfache Weg, dies mit GNU zu tun sed
:
sed --in-place '/some string here/d' yourfile
-r
Option (oder -E
, abhängig von Ihrer Version). Dies ermöglicht die Verwendung von Regex Metazeichen +
, ?
, {...}
und (...)
.
Sie können Folgendes in Betracht ziehen ex
(dies ist ein standardmäßiger befehlsbasierter Unix-Editor):
ex +g/match/d -cwq file
wo:
+
führt den angegebenen Ex-Befehl ( man ex
) aus, -c
der auch ausgeführt wird wq
(Schreiben und Beenden)g/match/d
- Ex-Befehl zum Löschen von Zeilen mit gegebenem match
, siehe: Potenz von gDas obige Beispiel ist eine POSIX-kompatible Methode zum direkten Bearbeiten einer Datei gemäß diesem Beitrag unter Unix.SE- und POSIX-Spezifikationen fürex
.
Der Unterschied zu sed
ist, dass:
sed
ist ein S tream ED itor, kein Dateieditor. BashFAQ
Es sei denn, Sie genießen nicht portierbaren Code, E / A-Overhead und einige andere schlimme Nebenwirkungen. Grundsätzlich sind einige Parameter (wie z. B. in-place / -i
) nicht standardmäßige FreeBSD-Erweiterungen und möglicherweise unter anderen Betriebssystemen nicht verfügbar.
man ex
es gibt mir den Mann vim
, so scheint es , ex
ist ein Teil von vim ... wenn ich für richtig , dass Mittel , um die Muster - Syntax zu verstehen match
ist vimregex.com , die POSIX und PCRE Aromen ähnlich , aber anders ist?
:g
ist ein POSIX-kompatibler Befehl mit einigen geringfügigen Unterschieden . Ich gehe davon aus, dass PCRE darauf basiert.
Ich hatte auf dem Mac damit zu kämpfen. Außerdem musste ich es mit variablem Ersatz machen.
Also habe ich verwendet:
sed -i '' "/$pattern/d" $file
Wo $file
ist die Datei, in der das Löschen erforderlich ist, und wo $pattern
ist das Muster, das zum Löschen abgeglichen werden soll?
Ich habe das ''
aus diesem Kommentar ausgewählt .
Hier ist die Verwendung von doppelten Anführungszeichen in zu beachten "/$pattern/d"
. Variable funktioniert nicht, wenn wir einfache Anführungszeichen verwenden.
sed
benötigt einen Parameter nach -i
. Wenn Sie also keine Sicherung wünschen, müssen Sie immer noch eine leere Zeichenfolge hinzufügen:-i ''
sed -i "/$pattern/d" $file
. Vielen Dank für Ihre Antwort.
Ich habe einen kleinen Benchmark mit einer Datei erstellt, die ungefähr 345 000 Zeilen enthält. Der Weg mit grep
scheint sed
in diesem Fall etwa 15-mal schneller zu sein als die Methode.
Ich habe sowohl mit als auch ohne die Einstellung LC_ALL = C versucht, 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 -v
wird nur ein anderes Muster als Ihr Muster gedruckt (dies bedeutet, dass die Übereinstimmung umgekehrt wird).
perl -i -nle'/regexp/||print' file1 file2 file3
perl -i.bk -nle'/regexp/||print' file1 file2 file3
Der erste Befehl bearbeitet die Datei (en) an Ort und Stelle (-i).
Der zweite Befehl macht dasselbe, behält jedoch eine Kopie oder Sicherung der Originaldatei (en) bei, indem .bk zu den Dateinamen hinzugefügt wird (.bk kann in irgendetwas geändert werden).
Nur für den Fall, dass jemand dies für genaue Übereinstimmungen von Zeichenfolgen tun möchte, können Sie das -w
Flag in grep - w für das Ganze verwenden. Das heißt, wenn Sie beispielsweise die Zeilen mit der Nummer 11 löschen möchten, aber die Zeilen mit der Nummer 111 beibehalten möchten:
-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 -f
Flag, 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
-w, --word-regexp Select only those lines containing matches that form whole words.
vs.-x, --line-regexp Select only those matches that exactly match the whole line. For a regular expression pattern, this is like parenthesizing the pattern and then surrounding it with ^ and $.
cat filename | grep -v "pattern" > filename.1
mv filename.1 filename
um den behandelten Text in der Konsole anzuzeigen
cat filename | sed '/text to remove/d'
um behandelten Text in einer Datei zu speichern
cat filename | sed '/text to remove/d' > newfile
behandelte Textinformationen an eine vorhandene Datei anhängen
cat filename | sed '/text to remove/d' >> newfile
Um bereits behandelten Text zu behandeln, entfernen Sie in diesem Fall mehr Zeilen von dem, was entfernt wurde
cat filename | sed '/text to remove/d' | sed '/remove this too/d' | more
Das | more
wird Text in Blöcken von jeweils einer Seite anzeigen.
Sie können gute alte verwenden ed
in ähnlicher Weise , um eine Datei zu bearbeiten die Antwort , dass Anwendungen ex
. Der große Unterschied in diesem Fall besteht darin, dass ed
die Befehle über die Standardeingabe und nicht als Befehlszeilenargumente wie ex
can verwendet werden. Wenn Sie es in einem Skript verwenden, können Sie dies normalerweise verwenden, indem Sie printf
Befehle an das Skript weiterleiten :
printf "%s\n" "g/pattern/d" w | ed -s filename
oder mit einem Heredoc:
ed -s filename <<EOF
g/pattern/d
w
EOF