Come fare in modo che grep corrisponda solo se l'intera linea corrisponde?


104

Ho questi:

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

Volevo trovare una corrispondenza esatta di ABB.log.

Ma quando l'ho fatto

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

li mostra tutti.

Posso ottenere quello che volevo usando grep?

Risposte:


105

Specifica semplicemente le ancore regexp.

grep '^ABB\.log$' a.tmp

2
Sono necessari entrambi gli ancoraggi (^ e $).
user562374

2
Ben fatto! E se sto usando la regex per la corrispondenza da un file? "grep -f patterns a.tmp" ??
green69

@ green69 Con diversi anni di ritardo, ma puoi usare sed per aggiungere le ancore prima di passare gli schemi a grep:sed -r "s/^(.*)$/^\1$/" patterns.txt | egrep -f - a.tmp
Randoms

155
grep -Fx ABB.log a.tmp

Dalla pagina man di grep:

-F, --fixed-strings
Interpreta PATTERN come un (elenco di) stringhe fisse
-x, --line-regexp
Seleziona solo le corrispondenze che corrispondono esattamente all'intera riga.


2
non è stato possibile utilizzare -F sfortunatamente.
Johnyy

@ Johnyy No -F? sei su Solaris? Se l'uso così/usr/xpg4/bin/grep
Scrutinizer

9
Sto usando grepuno script bash e questa opzione è meglio che usare un'espressione regolare come suggerito nella risposta accettata. Perché ho qualche carattere speciale all'interno della variabile che sto cercando (come .) e non devo evitarli quando uso il comando.
Gustavo Straube

1
migliore risposta IMO perché consente caratteri speciali senza sfuggire
ReneGAED

1
È meglio perché funziona anche con le variabili.
ybenjira

23

Ecco cosa faccio, anche se usare gli ancoraggi è il modo migliore:

grep -w "ABB.log " a.tmp

Come questo .. tornerà Corrispondenza della prima riga
user765443

1
Ciò richiede uno spazio dopo ABB.log, che non è il caso generale, ovvero fallirà la maggior parte delle volte.
Jahid

3

La maggior parte dei suggerimenti fallirà se c'è anche un solo spazio iniziale o finale, il che sarebbe importante se il file viene modificato a mano. Questo lo renderebbe meno suscettibile in quel caso:

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

Un semplice ciclo while-read nella shell lo farebbe implicitamente:

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


1

Intendo aggiungere qualche spiegazione extra riguardo ai tentativi di OP e anche altre risposte.

Puoi usare anche la soluzione di John Kugelmans in questo modo:

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

quotando la stringa e facendo l'escape del punto ( .) non serve più il -Fflag.

È necessario eseguire l'escape del .(punto) (perché corrisponde a qualsiasi carattere (non solo .) se non è sfuggito) o utilizzare il -Fflag con grep. -Fflag lo rende una stringa fissa (non una regex).

Se non si cita la stringa, potrebbe essere necessario un doppio backslash per evitare il punto ( .):

grep -x ABB\\.log a.tmp


Test:

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


Nota:

  1. -x forza per abbinare l'intera linea.
  2. Le risposte che utilizzano un codice non di escape .senza -Fflag sono sbagliate.
  3. Puoi evitare il -xpassaggio avvolgendo la stringa del modello con ^e $. In questo caso assicurati di non usare -F, invece esegui l'escape di ., perché -Fimpedirà l'interpretazione regex di ^e $.


EDIT: (aggiunta di spiegazioni extra riguardo a @hakre):

Se vuoi far corrispondere una stringa che inizia con -, dovresti usare --con grep. Tutto ciò che segue --sarà considerato un input (non un'opzione).

Esempio:

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

Hai davvero sperimentato che -F mancava nel tuo caso? In caso affermativo, puoi per favore dire quale caso è stato?
hakre

@hakre Hai letto completamente la mia risposta? Ho spiegato (abbastanza chiaramente) perché -Fnon sarà necessario se l' .escape è corretta.
Jahid

Sicuro. Certo, sto solo chiedendo: era -Fdisponibile quando hai scritto questo? In caso contrario, quale sistema stavi utilizzando? Finora non sono riuscito a trovare quell'informazione nella tua risposta, cosa che accade anche adesso quando l'ho riletta di nuovo. Quindi, davvero sicuro, ho letto la tua risposta completamente almeno due volte. ;)
hakre

@hakre Ovviamente -Fera disponibile. (Ho detto: "o usa -Fbandiera con grep")
Jahid

Grazie per l'intuizione. Rimane solo una piccola domanda: se -Fè la risposta, perché preoccuparsi di scappare? Qual è la tua opinione al riguardo?
hakre

1

Questo ha funzionato bene per me quando cercavo di fare qualcosa di simile:

grep -F ABB.log a.tmp

-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
    $

1
Ciò corrisponderà anche ai file che terminano con ABB.log e i punti dovrebbero essere eliminati.
Scrutinizer

-1

Funziona per me :

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

\b indica / imposta i confini.

Sembra funzionare abbastanza velocemente


Ciò corrisponde anche a qualsiasi riga che contiene search_wordseparati da confini di parola. Ad esempio, corrisponderebbe alla riga "foo search_word bar".
Rohan Singh

-2

Questo è con HPUX, se il contenuto dei file ha spazio tra le parole, usa questo:

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


L'OP voleva far corrispondere l'intera riga, non una parola delimitata da spazi all'interno della riga.
Keith Thompson


-3

Avevo bisogno di questa funzionalità, ma volevo anche assicurarmi di non restituire righe con un prefisso prima di ABB.log:

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

grep "\WABB.log$" -w a.tmp

Questo corrisponderà solo se l'interlinea \Wè soddisfatta, che è qualsiasi carattere diverso da uno spazio bianco, quindi xABBxlog.
bschlueter
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.