web-dev-qa-db-fra.com

Utiliser le signe étoile dans grep

J'essaie de rechercher la sous-chaîne "abc" dans un fichier spécifique sous linux/bash

Moi aussi:

grep '*abc*' myFile

Cela ne retourne rien.

Mais si je le fais:

grep 'abc' myFile

Il retourne les correspondances correctement.

Maintenant, ce n'est pas un problème pour moi. Mais si je veux grep pour une chaîne plus complexe, disons

*abc * def *

Comment pourrais-je l'accomplir en utilisant grep?

61
Saobi

L'astérisque est juste un opérateur de répétition , mais vous devez lui dire ce que vous répétez. /*abc*/ correspond à une chaîne contenant ab et zéro ou plusieurs c (parce que le second * est sur le c; le premier n'a pas de sens car il n'y a rien à répéter). Si vous voulez faire correspondre quelque chose, vous devez dire .* - le point signifie n'importe quel caractère ( dans certaines directives ). Si vous voulez juste faire correspondre abc, vous pouvez simplement dire grep 'abc' myFile. Pour votre correspondance plus complexe, vous devez utiliser .* - grep 'abc.*def' myFile fera correspondre une chaîne contenant abc suivie de def avec un élément facultatif entre les deux.

Mise à jour basée sur un commentaire:

* dans une expression régulière n'est pas exactement identique à * dans la console. Dans la console, * fait partie d'un glob construct , et agit simplement comme un caractère générique (par exemple, ls *.log liste tous les fichiers se terminant par .log). Cependant, dans les expressions régulières, * est un modificateur, ce qui signifie qu'il ne s'applique qu'au caractère ou au groupe le précédant. Si vous voulez que * dans les expressions régulières agisse comme un caractère générique, vous devez utiliser .* comme mentionné précédemment - le point est un caractère générique et l'étoile, lors de la modification du point, signifie que vous recherchez un ou plusieurs points; c'est à dire. trouver un ou plusieurs personnages.

91
Daniel Vandersluis

Le caractère point signifie qu’il correspond à n’importe quel caractère, donc .* signifie zéro ou plusieurs occurrences de tout caractère. Vous voulez probablement utiliser .* plutôt que simplement *.

14
smcameron

Le "signe en étoile" n'a de sens que s'il y a quelque chose devant. S'il n'y a pas d'outil (grep dans ce cas), il peut simplement le traiter comme une erreur. Par exemple:

'*xyz'    is meaningless
'a*xyz'   means zero or more occurrences of 'a' followed by xyz
10
anon

L'expression que vous avez essayée, comme celles qui fonctionnent sur la ligne de commande Shell sous Linux par exemple, s'appelle " glob ". Les expressions globales ne sont pas complètes expressions régulières , qui est ce que grep utilise pour spécifier les chaînes à rechercher. Ici est (ancien, petit) post sur les différences. Les expressions globales (comme dans "ls *") sont interprétées par le shell lui-même.

Il est possible de traduire des globes en entités génériques, mais vous devez généralement le faire dans votre tête.

5
unwind

Vous n'utilisez pas d'expressions régulières, votre variante de choix de grep doit donc être fgrep, qui se comportera comme vous le souhaitez.

4
Andrew Beals

Essayez grep -E pour la prise en charge étendue des expressions régulières

Regardez aussi:

La page de manuel de grep

3
Brian

Utilisez grep -P - qui active la prise en charge des expressions régulières de style Perl.

grep -P "abc.*def" myfile
3
Artem Russakovskii

C'est peut-être la réponse que vous cherchez:

grep abc MyFile | grep def

La seule chose à faire est que ... les lignes de sortie où "def" est avant OR après "abc"

1
Charles Duke

'*' fonctionne comme un modificateur pour l'élément précédent. Donc 'abc * def' recherche 'ab' suivi de 0 ou plus 'c suivi de' def '.

Ce que vous voulez probablement, c'est "abc. * Def" qui recherche "abc" suivi d'un nombre quelconque de caractères, suivi de "def".

0

Cela a fonctionné pour moi:

grep ". * $ {expr}" - avec des guillemets doubles, précédés du point, grep standard avec des commutateurs supplémentaires.

0
access_granted