Comment faire en sorte que grep ne corresponde que si la ligne entière correspond?

104

J'ai ceux-ci:

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

Je voulais trouver une correspondance exacte de ABB.log.

Mais quand je l'ai fait

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

il les montre tous.

Puis-je obtenir ce que je voulais en utilisant grep?

Johnyy
la source

Réponses:

105

Spécifiez simplement les ancres de l'expression rationnelle.

grep '^ABB\.log$' a.tmp
user562374
la source
2
Les deux ancres (^ et $) sont nécessaires.
user562374
2
Joli! Et si j'utilise l'expression régulière pour la correspondance à partir d'un fichier? "grep -f modèles a.tmp" ??
green69
@ green69 Plusieurs années de retard, mais vous pouvez utiliser sed pour ajouter les ancres avant de passer les motifs à grep:sed -r "s/^(.*)$/^\1$/" patterns.txt | egrep -f - a.tmp
Random
155
grep -Fx ABB.log a.tmp

Depuis la page de manuel grep:

-F, --fixed-strings
Interpréter PATTERN comme une (liste de) chaînes fixes
-x, --line-regexp
Sélectionnez uniquement les correspondances qui correspondent exactement à la ligne entière.

John Kugelman
la source
2
n'a pas pu utiliser -F malheureusement.
Johnyy
@Johnyy Non -F? êtes-vous sur Solaris? Si c'est le cas, utilisez/usr/xpg4/bin/grep
Scrutinizer
9
j'utilise grep dans un script bash et cette option est meilleure que d'utiliser une expression régulière comme suggéré dans la réponse acceptée. Parce que j'ai un caractère spécial dans la variable que je recherche (comme .) et que je n'ai pas à les échapper lors de l'utilisation de la commande.
Gustavo Straube
1
meilleure réponse IMO car il permet les caractères spéciaux sans échapper
ReneGAED
1
C'est mieux car cela fonctionne également avec des variables.
ybenjira
23

Voici ce que je fais, mais utiliser des ancres est le meilleur moyen:

grep -w "ABB.log " a.tmp
PranavKN
la source
Comme celui-ci .. il reviendra Match de première ligne
user765443
1
Cela nécessite un espace après ABB.log, ce qui n'est pas le cas général, c'est-à-dire qu'il échouera la plupart du temps.
Jahid
3

La plupart des suggestions échoueront s'il n'y a qu'un seul espace de début ou de fin, ce qui serait important si le fichier est édité à la main. Cela le rendrait moins sensible dans ce cas:

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

Une simple boucle while-read dans le shell le ferait implicitement:

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

de même avec awk

 awk '/^ABB\.log$/' file
ghostdog74
la source
1

J'ai l'intention d'ajouter quelques explications supplémentaires concernant les tentatives d'OP et d'autres réponses également.

Vous pouvez également utiliser la solution de John Kugelmans comme ceci:

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

citer la chaîne et échapper le point ( .) fait qu'il n'a plus besoin du -Fdrapeau.

Vous devez échapper le .(point) (car il correspond à n'importe quel caractère (pas seulement .) s'il n'est pas échappé) ou utiliser l' -Findicateur avec grep.-Fflag en fait une chaîne fixe (pas une expression régulière).

Si vous ne citez pas la chaîne, vous aurez peut-être besoin d'une double barre oblique inverse pour échapper au point ( .):

grep -x ABB\\.log a.tmp


Tester:

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


Remarque:

  1. -x forces pour correspondre à toute la ligne.
  2. Réponses utilisant un non échappé .sans-F indicateur sont fausses.
  3. Vous pouvez éviter le -xbasculement en enveloppant votre chaîne de motif avec ^et $. Dans ce cas, assurez-vous de ne pas utiliser -F, mais échappez à la place ., car -Fcela empêchera l'interprétation regex de ^et $.


EDIT: (Ajout d'explications supplémentaires en ce qui concerne @hakre):

Si vous souhaitez faire correspondre une chaîne commençant par -, vous devez utiliser --avec grep. Tout ce qui suit --sera considéré comme une entrée (pas une option).

Exemple:

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
la source
Avez-vous réellement constaté que -F manquait dans votre cas? Dans l'affirmative, pouvez-vous nous dire de quel cas il s'agissait?
hakre
@hakre Avez-vous lu ma réponse complètement? J'ai expliqué (assez clairement) pourquoi -Fne sera pas nécessaire si le .est correctement échappé.
Jahid
Sûr. Bien sûr, je demande simplement: était -Fdisponible lorsque vous avez écrit ceci? Sinon, quel système utilisiez-vous? Je n'ai pas trouvé cette information dans votre réponse jusqu'à présent, ce qui est encore le cas lorsque je la relis. Alors vraiment sûr, j'ai lu votre réponse complètement au moins deux fois. ;)
hakre
@hakre Bien sûr, -Fétait disponible. (J'ai dit: "ou utiliser un -Fdrapeau avec grep")
Jahid
Merci pour la perspicacité. Il ne reste qu'une petite question: si -Fest la réponse, pourquoi s'embêter à s'échapper? Quelle est votre opinion à ce sujet?
hakre
1

Cela a bien fonctionné pour moi lorsque j'ai essayé de faire quelque chose de similaire:

grep -F ABB.log a.tmp
Fred Christophe
la source
-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
la source
1
Cela correspondra également aux fichiers qui se terminent par ABB.log et les points doivent être échappés.
Scrutinizer
-1

Fonctionne pour moi :

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

\b indique / fixe des limites.

Semble fonctionner assez vite

Surya
la source
Cela correspond également à toute ligne contenant search_worddes limites de mots séparées. Par exemple, il correspondrait à la ligne "foo search_word bar".
Rohan Singh
-2

C'est avec HPUX, si le contenu des fichiers a un espace entre les mots, utilisez ceci:

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

user3114790
la source
L'OP voulait faire correspondre la ligne entière, pas un mot délimité par des espaces dans la ligne.
Keith Thompson
-3

Je préfèrerais:

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

à votre santé

Bartosz
la source
Cela correspondraABBxlog
Keith Thompson
-3

J'avais besoin de cette fonctionnalité, mais je voulais aussi m'assurer de ne pas renvoyer de lignes avec un préfixe avant ABB.log:

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

grep "\WABB.log$" -w a.tmp
Jonathan
la source
Cela ne correspondra que si le début \West satisfait, qui est un caractère non blanc, donc xABBxlog.
bschlueter