web-dev-qa-db-fra.com

Grep: L'astérisque (*) ne fonctionne pas toujours

Si je grep un document qui contient ce qui suit:

ThisExampleStringname__

... pour l'expression This*String ou *String, rien n'est renvoyé. Cependant, This* renvoie la ligne ci-dessus comme prévu.

Que l'expression soit entre guillemets ne fait aucune différence.

Je pensais que l'astérisque indiquait un nombre quelconque de caractères inconnus? Pourquoi ça marche seulement si c'est au début de l'expression? Si cela est prévu, que dois-je utiliser à la place des expressions This*String et *String?

8
Trae

Un astérisque dans expressions régulières signifie "faire correspondre l'élément précédent 0 fois ou plus".

Dans votre cas particulier avec grep 'This*String' file.txt, vous essayez de dire: "hé, grep, faites-moi correspondre au mot Thi, suivi de s minuscule zéro ou plusieurs fois, suivi du mot String". La s minuscule est introuvable dans Example, donc grep ignore ThisExampleString.

Dans le cas de grep '*String' file.txt, vous dites "grep, faites-moi correspondre la chaîne vide - littéralement rien - précédant le mot String". Bien sûr, ce n’est pas ainsi que ThisExampleString est censé être lu. (Il y a autres significations possibles - vous pouvez essayer ceci avec et sans le drapeau -E - mais aucune des significations ne ressemble à ce que vous voulez vraiment ici.)

Sachant que . signifie "n'importe quel caractère", nous pourrions faire ceci: grep 'This.*String' file.txt. Maintenant, la commande grep le lira correctement: This suivi de n’importe quel caractère (pensez à cela comme sélection de caractères ASCII) répété autant de fois que nécessaire, suivi de String.

15

Le métacaractère * dans BRE1s, ERE1s et PCRE1s correspond à 0 ou plus occurrences du motif précédemment groupé (si un motif groupé précède le métacaractère *), à 0 ou plus occurrences de la classe de caractères précédente (si une classe de caractères est précédant au métacaractère *)) ou à 0 ou plus caractère précédent (si ni un modèle groupé ni une classe de caractères ne précèdent le métacaractère *);

Cela signifie que dans le modèle This*String, le métacaractère * n'étant précédé ni d'un modèle groupé ni d'une classe de caractères, le métacaractère * correspond à 0 ou plusieurs occurrences du caractère précédent (dans ce cas, le caractère sname__):

% cat infile               
ThisExampleString
ThisString
ThissString
% grep 'This*String' infile
ThisString
ThissString

Pour faire correspondre au moins 0 occurrences d'un caractère, vous souhaitez faire correspondre au moins 0 occurrences du métacaractère ., qui correspond à n'importe quel caractère:

% cat infile               
ThisExampleString
% grep 'This.*String' infile
ThisExampleString

Le métacaractère * dans les BRE et les ERE est toujours "gourmand", c'est-à-dire qu'il correspond à la correspondance la plus longue:

% cat infile
ThisExampleStringIsAString
% grep -o 'This.*String' infile
ThisExampleStringIsAString

Ce n'est peut-être pas le comportement souhaité. Si ce n'est pas le cas, vous pouvez activer le moteur PCRE de grepname __ (à l'aide de l'option -P) et ajouter le métacaractère ? qui, après le * et le + méta-caractères, a pour effet de modifier leur apparence.

% cat infile
ThisExampleStringIsAString
% grep -Po 'This.*?String' infile
ThisExampleString

1: expressions régulières de base, expressions régulières étendues et expressions régulières compatibles avec Perl

8
kos

Une explication trouvée ici lien :

L'astérisque "*" ne signifie pas la même chose dans les expressions régulières et dans les caractères génériques; c'est un modificateur qui s'applique au caractère simple précédent, ou à une expression telle que [0-9]. Un astérisque correspond à zéro ou plus de ce qui le précède. Ainsi, [A-Z]* correspond à n’importe quel nombre de lettres majuscules, y compris aucune, tandis que [A-Z][A-Z]* correspond à une ou plusieurs lettres majuscules.

4
Ova