Wie kann man grep nur dann übereinstimmen lassen, wenn die gesamte Zeile übereinstimmt?

101

Ich habe diese:

$ cat a.tmp
ABB.log
ABB.log.122
ABB.log.123

Ich wollte eine genaue Übereinstimmung von ABB.log finden.

Aber als ich es tat

$ grep -w ABB.log a.tmp
ABB.log
ABB.log.122
ABB.log.123

es zeigt sie alle.

Kann ich mit grep bekommen, was ich wollte?

Johnyy
quelle

Antworten:

105

Geben Sie einfach die regulären Ausdrucksanker an.

grep '^ABB\.log$' a.tmp
user562374
quelle
2
Beide Anker (^ und $) werden benötigt.
user562374
2
Schön! Und wenn ich den regulären Ausdruck für den Abgleich aus einer Datei verwende? "grep -f Muster a.tmp" ??
grün69
@ green69 Einige Jahre zu spät, aber Sie können sed verwenden, um die Anker hinzuzufügen, bevor Sie die Muster an grep übergeben:sed -r "s/^(.*)$/^\1$/" patterns.txt | egrep -f - a.tmp
Randoms
153
grep -Fx ABB.log a.tmp

Von der grep-Manpage:

-F, --fixed-strings
Interpretieren Sie PATTERN als (Liste) fester Zeichenfolgen
-x, --line-regexp
Wählen Sie nur die Übereinstimmungen aus, die genau mit der gesamten Zeile übereinstimmen.

John Kugelman
quelle
2
konnte -F leider nicht benutzen.
Johnyy
@ Johnyy Nein -F? Sind Sie auf Solaris? Wenn ja, verwenden Sie/usr/xpg4/bin/grep
Scrutinizer
9
Ich verwende grepin einem Bash-Skript und diese Option ist besser als die Verwendung eines regulären Ausdrucks, wie in der akzeptierten Antwort vorgeschlagen. Da die Variable, nach der ich suche (wie .), ein Sonderzeichen enthält, muss ich sie bei Verwendung des Befehls nicht umgehen.
Gustavo Straube
1
beste Antwort IMO, weil es Sonderzeichen erlaubt, ohne zu entkommen
ReneGAED
1
Dies ist besser, da es auch mit Variablen funktioniert.
Ybenjira
23

Folgendes mache ich, obwohl die Verwendung von Ankern der beste Weg ist:

grep -w "ABB.log " a.tmp
PranavKN
quelle
Wie dieses .. es wird First Line Match zurückgeben
user765443
Dies erfordert ein Leerzeichen danach ABB.log, was nicht der allgemeine Fall ist, dh es wird die meiste Zeit fehlschlagen.
Jahid
3

Die meisten Vorschläge schlagen fehl, wenn nur ein einziger führender oder nachfolgender Bereich vorhanden ist. Dies wäre wichtig, wenn die Datei von Hand bearbeitet wird. Dies würde es in diesem Fall weniger anfällig machen:

grep '^[[:blank:]]*ABB\.log[[:blank:]]*$' a.tmp

Eine einfache while-read-Schleife in der Shell würde dies implizit tun:

while read file
do 
  case $file in
    (ABB.log) printf "%s\n" "$file"
  esac
done < a.tmp
Scrutinizer
quelle
2

ähnlich mit awk

 awk '/^ABB\.log$/' file
Ghostdog74
quelle
1

Ich beabsichtige, einige zusätzliche Erklärungen zu den Versuchen von OP und anderen Antworten hinzuzufügen.

Sie können die Lösung von John Kugelmans auch folgendermaßen verwenden:

grep -x "ABB\.log" a.tmp

Wenn Sie den String zitieren und dem Punkt ( .) entkommen, wird das -FFlag nicht mehr benötigt.

Sie müssen den .(Punkt) maskieren (da er mit einem beliebigen Zeichen übereinstimmt (nicht nur .), wenn er nicht maskiert ist) oder das -FFlag mit grep verwenden. -FFlag macht es zu einer festen Zeichenfolge (kein regulärer Ausdruck).

Wenn Sie die Zeichenfolge nicht zitieren, benötigen Sie möglicherweise einen doppelten Backslash, um den Punkt ( .) zu umgehen :

grep -x ABB\\.log a.tmp


Prüfung:

$ echo "ABBElog"|grep -x  ABB.log
ABBElog #matched !!!
$ echo "ABBElog"|grep -x  "ABB\.log"
#returns empty string, no match


Hinweis:

  1. -x zwingt, die ganze Linie anzupassen.
  2. Antworten mit einem nicht entkommenen Flag .ohne -FFlag sind falsch.
  3. Sie können einen -xWechsel vermeiden , indem Sie Ihre Musterzeichenfolge mit ^und umschließen $. Stellen Sie in diesem Fall sicher, dass Sie nicht verwenden -F, sondern dem entkommen ., da dies -Fdie Regex-Interpretation von ^und verhindert $.


BEARBEITEN: (Zusätzliche Erklärung in Bezug auf @hakre hinzufügen):

Wenn Sie eine Zeichenfolge ab beginnen möchten, -sollten Sie sie --mit grep verwenden. Was auch immer folgt, --wird als Eingabe verwendet (keine Option).

Beispiel:

echo -f |grep -- "-f"     # where grep "-f" will show error
echo -f |grep -F -- "-f"  # whre grep -F "-f" will show error
grep "pat" -- "-file"     # grep "pat" "-file" won't work. -file is the filename
Jahid
quelle
Haben Sie tatsächlich erfahren, dass -F in Ihrem Fall fehlte? Wenn ja, können Sie bitte sagen, welcher Fall das war?
hakre
@hakre Hast du meine Antwort vollständig gelesen? Ich erklärte (ziemlich klar), warum -Fnicht benötigt wird, wenn das .richtig entkommen ist.
Jahid
Sicher. Klar, ich frage nur: War -Fverfügbar, als du das geschrieben hast? Wenn nicht, welches System haben Sie verwendet? Ich konnte diese Informationen in Ihrer Antwort bisher nicht finden, was auch jetzt noch der Fall ist, wenn ich sie erneut lese. Also wirklich sicher, ich habe Ihre Antwort mindestens zweimal vollständig gelesen. ;)
hakre
@akre war natürlich -Fvorhanden. (Ich sagte: "oder benutze -FFlagge mit grep")
Jahid
Danke für den Einblick. Es bleibt nur eine kleine Frage: Wenn -Fdie Antwort lautet, warum sollte man sich dann die Mühe machen, zu fliehen? Was ist deine Meinung dazu?
hakre
1

Das hat bei mir gut funktioniert, als ich versucht habe, etwas Ähnliches zu tun:

grep -F ABB.log a.tmp
Fred Christophe
quelle
-1
    $ cat venky
    ABB.log
    ABB.log.122
    ABB.log.123

    $ cat venky | grep "ABB.log" | grep -v "ABB.log\."
    ABB.log
    $

    $ cat venky | grep "ABB.log.122" | grep -v "ABB.log.122\."
    ABB.log.122
    $
user2173461
quelle
1
Dies stimmt auch mit Dateien überein, die mit ABB.log enden, und die Punkte sollten maskiert werden.
Scrutinizer
-1

Funktioniert für mich :

grep "\bsearch_word\b" text_file > output.txt  

\b zeigt / setzt Grenzen.

Scheint ziemlich schnell zu arbeiten

Surya
quelle
Dies entspricht auch jeder Zeile, search_worddie durch Wortgrenzen getrennte Zeilen enthält . Zum Beispiel würde es mit der Zeile "foo search_word bar" übereinstimmen.
Rohan Singh
-2

Dies ist bei HPUX der Fall, wenn der Inhalt der Dateien Leerzeichen zwischen Wörtern enthält: Verwenden Sie Folgendes:

egrep "[[:space:]]ABC\.log[[:space:]]" a.tmp

user3114790
quelle
Das OP wollte mit der gesamten Zeile übereinstimmen, nicht mit einem durch Leerzeichen getrennten Wort innerhalb der Zeile.
Keith Thompson
-3

Ich würde bevorzugen:

str="ABB.log"; grep -E "^${str}$" a.tmp

Prost

Bartosz
quelle
Das wird passenABBxlog
Keith Thompson
-3

Ich brauchte diese Funktion, wollte aber auch sicherstellen, dass ich keine Zeilen mit einem Präfix vor dem ABB.log zurückgab:

  • ABB.log
  • ABB.log.122
  • ABB.log.123
  • 123ABB.log

grep "\WABB.log$" -w a.tmp
Jonathan
quelle
Dies stimmt nur überein, wenn der führende \WWert erfüllt ist, bei dem es sich also um ein Nicht-Leerzeichen handelt xABBxlog.
bschlueter