
Ich möchte eine Zeile aus einer Textdatei ( input.txt
) löschen, wenn zwei Muster ( string1
und string2
) auf derDasselbeZeile, mit sed
.
Ich versuche:
sed -i "/\b\(string1\|string2\)\b/d" input.txt
, aber dadurch werden Zeilen gelöscht, string1
die ODER enthalten string2
.
Antwort1
sed -i "/string1.*string2\|string2.*string1/d" input.txt
Dadurch werden alle Zeilen gelöscht, in denen string1 vor string2 steht ODER string2 vor string1 steht. Damit die Zeile gelöscht wird, müssen beide Zeichenfolgen in beliebiger Reihenfolge in der Zeile stehen.
Antwort2
sed -ie '/string1/!b' -e '/string2/d' file.txt
Dadurch werden Zeilen gelöscht, die sowohl als string1
auch enthalten string2
, unabhängig von der Reihenfolge (es kann sogar zu Überschneidungen kommen, wie etwa bei der Suche nach foobar
in barbaz
in einer Zeile, die enthält foobarbaz
).
-i
oben ist eine GNU-Erweiterung. Eine weitere GNU-spezifische Lösung¹:
awk -i /usr/share/awk/inplace.awk '!(/string1/ && /string2/)' file.txt
Für den mobilen Einsatz würden Sie wahrscheinlich perl
Folgendes verwenden:
perl -ni -e 'print unless /string1/ && /string2/'
¹verwende nicht-i inplace
as versucht zunächst, die Erweiterung (as oder ) aus dem aktuellen Arbeitsverzeichnis gawk
zu laden , wo jemand Malware platziert haben könnte. Der Pfad der mit gelieferten Erweiterung kann je nach System unterschiedlich sein, siehe die Ausgabe voninplace
inplace
inplace.awk
inplace
gawk
gawk 'BEGIN{print ENVIRON["AWKPATH"]}'
Antwort3
Verwenden vonRaku(früher bekannt als Perl_6)
~$ raku -ne '.put unless .match(/ foobar / & / barbaz / ) ;' file
ODER
~$ raku -ne '.put unless grep({ / foobar / & / barbaz / }, $_ ) ;' file
Oben sind zwei allgemeine Möglichkeiten aufgeführt, die Aufgabe des OP mit Raku zu erfüllen. Beachten Sie, grep
dass Raku Perl ähnelt grep
, außer dass nach dem Block ein Komma erforderlich ist. Sie können .grep
stattdessen auch den Methodenaufruf verwenden und müssen sich nicht um das Schreiben $_
in die Klammern kümmern.
Beide Codebeispiele oben löschen Zeilen, die zwei Zeichenfolgen enthalten,unabhängig von der Reihenfolge UND unabhängig davon, ob sich die Zeichenfolgen überschneiden.Zum Beispiel:
Beispieleingabe:
1 foo
2 bar
3 baz
4 foobar
5 foobaz
6 barbaz
7 foobar foobaz
8 foobaz barbaz
9 foobar barbaz
10 foobar foobaz barbaz
11 foobaz barbaz foobar
12 barbaz foobar foobaz
13 foobarbaz
Beispielausgabe (entweder der Codebeispiele oben):
1 foo
2 bar
3 baz
4 foobar
5 foobaz
6 barbaz
7 foobar foobaz
8 foobaz barbaz
Der obige Code löscht die Zeilen 9 bis 13, einschließlich Zeile 13, foobarbaz
die die Überlappung von string1 und string2 enthält. Wenn Sie Zeichenfolgen löschen müssen, die in einer bestimmten Reihenfolge (und ohne Überlappung) erscheinen, kann Raku das auch tun:
~$ raku -ne '.put unless m/foobar .* barbaz/;' file
Oben werden die Zeilen 9 und 10 entfernt: foobar barbaz
und foobar foobaz barbaz
.
Beachten Sie, dass Sie mit Raku-Regexendürfenerkennt zwei sich überschneidende Zeichenfolgen mit dem Parameter/Adverb :overlap
(oder :ov
). Siehe ersten Link unten.
https://docs.raku.org/language/regexes#Overlap
https://docs.raku.org/language/regexes
https://raku.org