Ich habe versucht, eine Zeile zu filtern, in der die Wörter "Zitrone" und "Reis" vorkommen. Ich weiß, wie man "Zitrone" oder "Reis" findet, aber nicht die beiden. Sie müssen nicht nebeneinander stehen, sondern nur dieselbe Textzeile.
Ich habe versucht, eine Zeile zu filtern, in der die Wörter "Zitrone" und "Reis" vorkommen. Ich weiß, wie man "Zitrone" oder "Reis" findet, aber nicht die beiden. Sie müssen nicht nebeneinander stehen, sondern nur dieselbe Textzeile.
Antworten:
"Beide in derselben Zeile" bedeutet "Reis", gefolgt von zufälligen Zeichen, gefolgt von "Zitrone" oder umgekehrt ".
In Regex ist das rice.*lemon
oder lemon.*rice
. Sie können dies kombinieren mit |
:
grep -E 'rice.*lemon|lemon.*rice' some_file
Wenn Sie normale reguläre Ausdrücke anstelle von erweiterten Ausdrücken ( -E
) verwenden möchten, müssen Sie vor dem |
folgenden Schrägstrich einen umgekehrten Schrägstrich einfügen :
grep 'rice.*lemon\|lemon.*rice' some_file
Für mehr Wörter, die schnell etwas länger werden und es normalerweise einfacher ist, mehrere Aufrufe von zu verwenden grep
, zum Beispiel:
grep rice some_file | grep lemon | grep chicken
grep rice
findet Zeilen mit rice
. Es wird eingespeist, in grep lemon
die nur zitronenhaltige Zeilen gelangen. Während der OP - sowie Ihre vorherigen Antworten - erlaubt jeder von [Reis | Zitrone | Huhn]
|
man entkommen muss grep
? Vielen Dank!
egrep
verwendet erweiterte reguläre Ausdrücke, wobei dies |
als ODER-Logik verstanden wird. grep
Der \|
grep
der Manpage von angegeben, egrep
ist veraltet und sollte durch ersetzt werden grep -E
. Ich habe mir die Freiheit genommen, die Antwort entsprechend zu bearbeiten.
Sie können die Ausgabe des ersten grep-Befehls an einen anderen grep-Befehl leiten, der beiden Mustern entspricht. Sie können also Folgendes tun:
grep <first_pattern> <file_name> | grep <second_pattern>
oder,
cat <file_name> | grep <first_pattern> | grep <second_pattern>
Fügen wir unserer Datei einige Inhalte hinzu:
$ echo "This line contains lemon." > test_grep.txt
$ echo "This line contains rice." >> test_grep.txt
$ echo "This line contains both lemon and rice." >> test_grep.txt
$ echo "This line doesn't contain any of them." >> test_grep.txt
$ echo "This line also contains both rice and lemon." >> test_grep.txt
Was enthält die Datei:
$ cat test_grep.txt
This line contains lemon.
This line contains rice.
This line contains both lemon and rice.
This line doesn't contain any of them.
This line also contains both rice and lemon.
Lassen Sie uns nun sagen, was wir wollen:
$ grep rice test_grep.txt | grep lemon
This line contains both lemon and rice.
This line also contains both rice and lemon.
Wir erhalten nur die Linien, bei denen beide Muster übereinstimmen. Sie können dies erweitern und die Ausgabe für weitere "AND" -Matches an einen anderen grep-Befehl leiten.
grep mit -P
(Perl-Compatibility) Option und positivem Lookahead Regex(?=(regex))
:
grep -P '(?=.*?lemon)(?=.*?rice)' infile
oder Sie können stattdessen unten verwenden:
grep -P '(?=.*?rice)(?=.*?lemon)' infile
.*?
bedeutet, dass alle Zeichen gefunden werden .
, die nicht oder mehrmals vorkommen, *
wenn sie optional sind, gefolgt von einem Muster ( rice
oder lemon
). Das ?
macht alles optional davor (bedeutet null oder einmal von allem zusammengepasst .*
)(?=pattern)
: Positiver Lookahead: Das positive Lookahead-Konstrukt besteht aus zwei Klammern, wobei die öffnende Klammer von einem Fragezeichen und einem Gleichheitszeichen gefolgt wird.
Dies gibt also alle Zeilen mit sowohl lemon
als auch rice
in zufälliger Reihenfolge zurück. Auch dies vermeidet die Verwendung von |
s und doppelten grep
s.
Externe Links:
Erweiterte Grep-Themen Positive Lookahead - GREP für Designer
Wenn wir zugeben, dass es grep
akzeptabel ist, eine Antwort zu liefern, die nicht auf der obigen Antwort basiert awk
, würde ich eine einfache perl
Zeile vorschlagen , wie:
$ perl -ne 'print if /lemon/ and /rice/' my_text_file
Die Suche kann Groß- / Kleinschreibung mit einigen / allen Wörtern ignorieren /lemon/i and /rice/i
. Auf den meisten Unix / Linux-Rechnern ist Perl genauso installiert wie awk.
Hier ist ein Skript zur Automatisierung der grep-Piping-Lösung:
#!/bin/bash
# Use filename if provided as environment variable, or "foo" as default
filename=${filename-foo}
grepand () {
# disable word splitting and globbing
IFS=
set -f
if [[ -n $1 ]]
then
grep -i "$1" ${filename} | filename="" grepand "${@:2}"
else
# If there are no arguments, assume last command in pipe and print everything
cat
fi
}
grepand "$@"
eval