2016-06-29 11 views
1

Lets sagen, ich habe eine Datei mitLöschen mehrerer Anpassungsmuster aus einer Datei

abc aab100 100 cdc 20aaab aaaan 
gshgds aab122 ghsgsd cdc aajksj aaasdan 
gsgdsg hqusu jsdjsd jksjks jskdk 
hjshj aab1jk uiuasu cdc 100ai bbcbxb 
arta hyiosa jkulp nnnnnak cdc 

ich zwei Muster passen wollen und wenn beide Muster vorhanden sind, möchte ich diese Zeile löschen.

Also hier mein Muster, die ich löschen möchten sind AAb1 und cdc

In der obigen Datei, diese beiden Muster entspricht in Zeile 1, Zeile 2 und Zeile 4. So würde Ich mag diese 3 Zeilen löschen

kann ich die Ergebnisse, die ich unter Verwendung von grep wollen als

grep -v 'aab1.*cdc' test.txt > test1.txt 

Auch kann ich dies ohne von

in eine neue Datei schreiben auf der gleichen Datei tun
echo "$(grep -v 'aab1.*cdc' test.txt)" > test.txt 

Aber gibt es eine andere bessere/schnellere/effiziente Möglichkeit, dies zu tun, ohne grep zu verwenden?

Dank

Antwort

1

Mit sed:

sed -i '/aab1.*cdc/d' file 

Die -i Option ist die Datei an Ort und Stelle bearbeiten.

+0

gab einen ''^:-). Die Op ist nicht klar darüber, ob die Muster getrennte Wörter sein sollen oder nicht. Aber nach dem, was ich aus den Versuchen von OP verstehe, sind separate Wörter keine Voraussetzung – sjsam

+0

Dank @sjsam. Dieses Muster funktioniert auch auf 'aab1cdc'. – SLePort

+0

Hier wird angenommen, dass die Reihenfolge auch angegeben ist. – karakfa

1

Mit grep für solche Aufgabe ist in Ordnung, das Hauptproblem mit Ihrem Code ist die Befehlsersetzung, da es die gesamte Ausgabe von grep in den Speicher geladen wird. Betrachten wir eine temporäre Datei mit:

grep -v 'aab1.*cdc' test.txt > tmp.txt && mv tmp.txt test.txt 

Alternative Sie mit -i sed verwendet wird, kann die Inplace Editing ermöglicht (Unter der Haube sed wird auch eine temporäre Datei verwenden):

sed -i '/aab1.*cdc/d' test.txt 

Es gibt auch sponge from moreutils die aufsaugt wird all seinen Eingang, bevor die Ausgabedatei zu öffnen:

grep -v 'aab1.*cdc' test.txt | sponge test.txt 

ich kann Ihnen nicht sagen, wie es aber (mit temporär implementiert ist y-Datei oder im Speicher gehalten)

1
sed -n '/aab1.*cdc/!p' test > test1 

sollten auch tun es

Kurz

Wir prüfen für das Muster aab1.*cdc in jeder Zeile und wenn es vorhanden ist, wir werden nicht gedruckt, die Linie. Die Standard-OUT ist mit einem test1

Hinweise

  1. -n zur Unterdrückung der normalen Ausgabe
  2. /pattern/ für den Mustervergleich benannte Datei umgeleitet wird.
  3. p ist zum Drucken von Zeilen. So !p negiert es. Dies überschreibt -n.

Perl

perl -ni -e 'print unless (m/aab1/ && m/cdc/)' file 

Hinweise

  1. -n für die normale Ausgabe
  2. -i für in-place Unterdrückung von EDI- t
  3. -e können Sie definieren, Perl-Code vom Compiler ausgeführt werden.
  4. m/aab1/ && m/cdc/ Übereinstimmungen (m) beide (&&) die Muster (/stuff/).
  5. print unless sorgt dafür, dass eine Zeile gedruckt wird, wenn beide Muster nicht vorhanden sind.

Eine weitere sed Lösung basierend auf [ @tripleee's ] Antwort

sed -n '/aab1/!{/cdc/!p}' test > test1 

Hinweise

Dies implementiert die in diesem awk[ solution ] wie erwähnt Verzweigung.

+0

Ist 'Perl' in diesem Fall schneller als 'sed'? –

+0

@mona_sax Mit den kleinen Daten glaube ich, dass "sed" in diesem Fall so schnell wie "perl" ist, kann aber nicht bestätigen. Die Op könnte dies bestätigen. – sjsam

1

Awk zur Rettung.

awk '!/aab1/ || !/cdc/' file 

Wenn aab1 nicht abgestimmt ist oder nicht cdc abgestimmt, (führen die Standardaktion, die zu), um die Zeile zu drucken.

Dies eignet sich gut für Szenarien, in denen Sie nicht auf die Reihenfolge der Übereinstimmungen achten, die schnell komplex wird, wenn Sie auf eine einzige Regex beschränkt sind.

Das gleiche in sed:

sed -e '/aab1/!b' -e '/cdc/d' file 

Generalisierung auf mehr als zwei Mustern, wenn ein Konflikt auf ein Muster ist, überspringen Sie den Rest dieses Skript für diese Linie. Wenn wir die letzte Regex erreichen, haben wir alle Muster angepasst, also löschen wir diese Zeile. (Ansonsten Abdruck.)

1

, wenn die Reihenfolge der Muster angegeben ist

$ awk '!/aab1.*cdc/' file 

wenn überhaupt möglich ist, um

$ awk '!(/aab1/ && /cdc/)' file 
Verwandte Themen