Utilisation du signe astrologique dans grep


87

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

Moi aussi:

grep '*abc*' myFile

Il ne renvoie rien.

Mais si je fais:

grep 'abc' myFile

Il renvoie correctement les correspondances.

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

*abc * def *

Comment pourrais-je y parvenir en utilisant grep?


3
grep lui-même ne prend pas en charge les caractères génériques sur la plupart des plateformes. Vous devez utiliser egrep pour utiliser des caractères génériques. Les shells ont une syntaxe différente. "*" dans le shell est <toute chaîne>. Dans egrep, c'est un opérateur qui dit "0 à plusieurs de l'entité précédente". Dans grep, c'est juste un caractère normal.
PanCrit

@PanCrit: *signifie la même chose dans grep et egrep: c'est un quantificateur signifiant zéro ou plus de l'atome précédent. C'est un concept complètement différent des caractères génériques utilisés par le shell.
Alan Moore

Réponses:


123

L'astérisque n'est qu'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 plus de c (parce que le deuxième * est sur le c; le premier n'a pas de sens parce qu'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 ( selon certaines directives ). Si vous voulez simplement faire correspondre abc, vous pouvez simplement dire grep 'abc' myFile. Pour votre correspondance plus complexe, vous devez utiliser .*- grep 'abc.*def' myFilecorrespondra à une chaîne contenant abc suivie de def avec quelque chose éventuellement entre les deux.

Mise à jour basée sur un commentaire:

*dans une expression régulière n'est pas exactement la même chose que * dans la console. Dans la console, * fait partie d'une construction glob , et agit simplement comme un joker (par exemple ls *.log, listera tous les fichiers qui se terminent par .log). Cependant, dans les expressions régulières, * est un modificateur, ce qui signifie qu'il s'applique uniquement au caractère ou au groupe qui le précède. 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 trouver un ou plusieurs points; c'est à dire. trouver un ou plusieurs de n'importe quel caractère.


1
Je pense que le questionneur est confus quant à la différence entre les caractères génériques de shell et les expressions régulières. Je soupçonne également que l'expression la plus compliquée serait: grep 'abc. * Def' (au moins un espace présent - peut-être deux comme je l'ai écrit).
Jonathan Leffler

1
En fait, le questionneur semble ne pas comprendre que 'abc' n'est pas la même chose que '^ abc $' :-D
Massa

1
Oui, j'étais confus entre glob et les expressions régulières complètes. J'utilise le * sans point pour signifier correspondre à quoi que ce soit sur le shell.
Saobi

1
grep *signifie "0 ou plus", et grep est gourmand par défaut. Notez que dans grep base des expressions régulières les métacaractères ?, +, {, |, (et )perdent leur signification particulière. Plus d'informations: grep regexps
KrisWebDev

24

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


Le point est un méta caractère qui accepte n'importe quel caractère sauf les nouvelles lignes .
Abhishek Kamal

12

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

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

5
Le * n'a pas de sens; il n'a tout simplement pas sa signification habituelle (de répétition) mais signifie "je suis une star". Cela correspondrait à une ligne contenant une étoile suivie de x, y et z.
Jonathan Leffler

2
@Jonathan Cela dépend de l'outil.

7

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

grep -P "abc.*def" myfile

6

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

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


1
Ce n'est qu'un glob s'il est analysé par le shell. Puisqu'il préserve la chaîne de recherche à l'intérieur de guillemets simples, le shell laisse la chaîne seule et la passe intacte dans argv à grep.
Compilateur remarquable

4

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


2
fgrepest désormais obsolète, grep -fdoit être utilisé à la place.
Prometheus

1
C'est "grep -F". Le bon vieux fgrep est peut-être "obsolète", mais ils ne vont pas le supprimer tant que je suis encore en vie.
Andrew Beals


1

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

grep abc MyFile | grep def

La seule chose est que ... il affichera les lignes où "def" est avant OU après "abc"


1

Cela a fonctionné pour moi:

grep ". * $ {expr}" - avec des guillemets doubles, précédés du point. Où "expr" est la chaîne dont vous avez besoin à la fin de la ligne.

Grep unix standard sans commutateurs supplémentaires.


0

'*' fonctionne comme un modificateur pour l'élément précédent. Donc 'abc * def' recherche 'ab' suivi de 0 ou plus de 'c suivis 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".

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.