Pourquoi `grep fil *` échoue?

9

J'ai trouvé echo file|grep fil*échoue, mais echo abcd|grep abc*réussit.

Je ne comprends pas, quelqu'un peut-il expliquer?

tmpbin
la source
Pouvez-vous ajouter le système et la version de grep? En effet, avec gnugrep 2.16 (sous Ubuntu 14.04 LTS), il ne génère aucune erreur (code de sortie 0) et correspond aux trois premières lettres. Par exemple, echo file|grep fil*répond avec file.
Hastur
3
@Hastur Le problème est dû à l'expansion du nom de fichier avant l'expression régulière. Mon répertoire de travail contient un fichier préfixé par fil, mais pas un fichier préfixé par abc, donc fil * est remplacé par le nom de fichier, mais abc * est inchangé.
tmpbin
Merci, je n'y ai pas pensé. Quand je fais mes tentatives je les essaie dans un nouveau répertoire ...
Hastur

Réponses:

31

Il y a deux problèmes avec votre exemple.

Le principal est que vous supposez que les expressions régulières fonctionnent de la même manière que les modèles globaux dans la mesure où il *s'agit d'un caractère générique signifiant "n'importe quelle séquence de caractères". Dans les expressions régulières, *signifie "n'importe quel nombre de l'atome précédent" à la place, donc fil*signifie fsuivi par isuivi de zéro ou plusieurs lcaractères. Vous devez dire grep fil.*pour obtenir la signification voulue: .signifie "n'importe quel caractère unique, ce qui .*signifie" n'importe quelle séquence de caractères ".

Le moindre problème est que vous utilisez des caractères spéciaux non cités qui signifient quelque chose selon les règles glob, ce qui signifie que le shell pourrait les interpréter. Si vous aviez des fichiers dans le répertoire local correspondant aux modèles glob fil*ou abc*, le shell les développait , donc greples noms de fichiers développés comme un modèle, et non le RE souhaité. Chaque fois que vous êtes en utilisant ces caractères sur la ligne de commande, vous devez les citer: echo file | grep 'fil.*'.

Warren Young
la source