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.*lemonoder 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 ricefindet Zeilen mit rice. Es wird eingespeist, in grep lemondie nur zitronenhaltige Zeilen gelangen. Während der OP - sowie Ihre vorherigen Antworten - erlaubt jeder von [Reis | Zitrone | Huhn]
|man entkommen muss grep? Vielen Dank!
egrepverwendet erweiterte reguläre Ausdrücke, wobei dies |als ODER-Logik verstanden wird. grepDer \|
grepder Manpage von angegeben, egrepist 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 ( riceoder 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 lemonals auch ricein zufälliger Reihenfolge zurück. Auch dies vermeidet die Verwendung von |s und doppelten greps.
Externe Links:
Erweiterte Grep-Themen Positive Lookahead - GREP für Designer
Wenn wir zugeben, dass es grepakzeptabel ist, eine Antwort zu liefern, die nicht auf der obigen Antwort basiert awk, würde ich eine einfache perlZeile 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