Finden Sie die genaue Zeichenfolge mit grep

9

Ich habe zum Beispiel eine große Textdatei mit vielen E-Mail-Adressen. Mit Bash muss ich suchen / überprüfen, ob eine E-Mail existiert (oder nicht). Sollte man (nur) die "Anker" verwenden?

grep '^[email protected]' text_file

oder gibt es bessere möglichkeiten Ich muss ein Bash-Skript erstellen und möchte sicher sein.

Pol Hallen
quelle
1
Ist die E-Mail das einzige Wort in einer Zeile?
Glenn Jackman
In der Tat: Die Datei hat folgendes Format: [email protected] example.com/user1
Pol Hallen
1
In diesem Fall würde ich grep -q '^user1@example\.com\>'- mit einem Zeilenanker am Anfang und einem Wortendanker am Ende verwenden.
Glenn Jackman

Antworten:

24

Siehe die Optionen -F(feste Zeichenfolge im Gegensatz zum regulären Ausdruck) und -x(genau: Übereinstimmung mit der gesamten Zeile).

grep -Fx [email protected] text_file

wäre das Äquivalent von:

grep '^user1@example\.com$' text_file

(Denken Sie daran, dass dies .ein Operator für reguläre Ausdrücke ist, der mit einem beliebigen Zeichen übereinstimmt.)

Verwenden Sie die -qOption, wenn Sie nur prüfen möchten, ob es eine solche Zeile gibt:

grep -Fxq [email protected] text_file &&
  echo yes, that address is in that file.

Wenn die zu durchsuchende Zeile und der Dateiname variabel sind:

grep -Fxqe "$email" < "$file"

Oder

grep -Fxq -- "$email" < "$file"

Du willst nicht:

grep -Fxq "$email" "$file"

da dies probleme verursachen würde wenn $emailoder $filemit -.

Wenn die Datei sortiert ist (vorzugsweise in Ihrem aktuellen Gebietsschema C), können Sie möglicherweise die Geschwindigkeit erhöhen, indem Sie commanstelle von grep:

printf '%s\n' [email protected] | comm -12 - text_file

Der Vorteil wird deutlicher, wenn Sie mehrere E-Mail-Adressen prüfen müssen (zum Beispiel in einer anderen sortierten Datei):

comm -12 text_file emails_to_check

wäre schneller als:

grep -Fxf emails_to_check text_file
Stéphane Chazelas
quelle
AFAIK grep -Fxq -- "$email" "$file"funktioniert auch.
Vinc17
stephane, warum hast du mit dem <redirector von einer dateieingabe (von grep verarbeitet) zu stdin gewechselt ? Gibt es irgendwelche Vorteile?
Umläute
@ umläute und vinc17. Wie gesagt, es soll für Dateinamen abdecken -. sogar grep -- "$email" "$file"wäre ein Problem für eine Datei namens -(die grepspeziell als Bedeutung stdin behandelt )
Stéphane Chazelas
5

Um so effizient wie möglich zu sein, möchten Sie anhalten, nachdem die erste Übereinstimmung gefunden wurde. Wenn Sie GNU haben grep, können Sie dies tun:

grep -m 1 '^user1@example\.com$' your_file

Andernfalls können Sie Perl verwenden:

perl -nlE 'say and last if $_ eq q{[email protected]}' your_file
Joseph R.
quelle
4
-mist GNU-spezifisch. Verwenden Sie POSIX, -qwenn Sie effizient prüfen möchten, ob eine solche Linie vorhanden ist.
Stéphane Chazelas
3

Dort gibt es viele E-Mail-Prüfungen. Eines davon ist:

grep -E -o "\b[a-zA-Z0-9.-]+@[a-zA-Z0-9.-]+\.[a-zA-Z0-9.-]+\b" text_file

Um meine Antwort zu erläutern.

Sie verwenden den ^Anker, der den Anfang der Zeichenfolge angibt. Dies stimmt nicht überein, wenn sich eine E-Mail-Adresse irgendwo zwischen einer langen Zeichenfolge befindet.

Valentin Bajrami
quelle
2
Vielen Dank. Dies ist eine generische grep-Option, um alle E-Mail-Adressen in einer Datei zu "extrahieren". Ich muss nach einer einzelnen E-Mail-Adresse suchen, indem ich EMAIL lese und dann grep benutze, um sie zu überprüfen.
Pol Hallen
2

Ihr grepBefehl stimmt mit allem überein, was beginnt ^[email protected], einschließlich der E-Mail-Adresse selbst, aber auch [email protected]. Da .es sich bei regulären Ausdrücken um ein Sonderzeichen handelt, das mit einem beliebigen Schlüssel übereinstimmt, sollten Sie es als maskieren\.

Unter der Annahme, dass Ihre Textdatei eine Adresse pro Zeile enthält, verwenden Sie:

EMAIL=user1@example\\.com
egrep "^${EMAIL}$" text_file

das abschließende $wird sicherstellen, dass die zeile nach der email-adresse endet. Ich benutze auch doppelte Anführungszeichen ", da diese erlauben, Variablen zu verwenden (im Gegensatz zu einfachen Anführungszeichen ')

umläute
quelle
1
Das passt auch user1@example-com.
Stéphane Chazelas
@ StéphaneChazelas du hast natürlich recht; hat die Antwort aktualisiert.
Umläute
@ umläute Du musst den Backslash verdoppeln. Aber es ist besser zu benutzen -Fx.
Vinc17
@ Vinc17, doh; Bash entkommen; sowieso ja, ich bin damit einverstanden, dass es besser ist zu verwenden, -Fxaber das ist stephanes antwort :-)
umläute
0

Unter Berücksichtigung der allgemeinen wörtlichen / genauen Übereinstimmung der Zeichenfolgen:

grep -w "search_word" <file>  >  output.txt

#\b shows boundaries over here.

oder,

 grep  "\bsearch_word\b"  <file>  >  output.txt 
123Benutzer
quelle