L'opérateur grep "+" ne fonctionne pas

31

Cette

ls -l /var/log | awk '{print $9}' | grep "^[a-z]*\.log."

sort ceci:

alternatives.log.1
alternatives.log.10.gz
alternatives.log.2.gz
alternatives.log.3.gz
alternatives.log.4.gz
alternatives.log.5.gz
alternatives.log.6.gz
alternatives.log.7.gz
alternatives.log.8.gz
alternatives.log.9.gz
apport.log.1
apport.log.2.gz
apport.log.3.gz

mais ça:

ls -l /var/log | awk '{print $9}' | grep "^[a-z]+\.log."

ne produit rien.

Pourquoi? Je viens de changer *pour +. N'est-ce pas similaire? L'opérateur a +juste besoin d'au moins une correspondance et de *zéro ou plus.

Marko
la source

Réponses:

36

C'est parce que grep(sans aucun argument) ne fonctionne qu'avec des expressions régulières standard. +fait partie des expressions régulières étendues, donc pour l'utiliser, vous devez utiliser grep -Eou egrep:

ls -l /var/log | awk '{print $9}' | grep -E "^[a-z]+\.log."

En outre, vous pouvez simplement le faire si vous ne souhaitez pas utiliser d'expressions régulières étendues:

ls -l /var/log | awk '{print $9}' | grep "^[a-z][a-z]*\.log."
MiJyn
la source
Merci. Je suis maintenant sur cette solution de contournement, mais je me demandais pourquoi "+" ne fonctionne pas. Maintenant je sais. Merci encore.
Marko
11

Pour développer la réponse de MiJyns, les "caractères spéciaux" comme + fonctionnent également dans les expressions rationnelles standard, mais vous devez leur échapper avec une barre oblique inverse. Vous pourriez dire que les attentes par défaut sont inversées entre l'expression régulière et l'expression régulière:

Dans l'expression régulière, les caractères correspondent littéralement par défaut. Par exemple, dans grep "ab+"le + est un + littéral. L'expression régulière trouverait par exemple "ab + ab", mais pas "abbbb". Pour utiliser la "signification spéciale" de +, vous devez y échapper. Ainsi grep "ab\+"trouverait "abbb", mais plus "ab + ab". Parce que dans le dernier exemple, le + est interprété comme le quantificateur "un ou plusieurs de cela", dans ce cas "un ou plusieurs b".

En regex étendu, c'est exactement l'inverse. Ici, vous devez échapper aux "caractères spéciaux" pour être traité littéralement. grep -E "ab+"Trouve donc "abbb", mais pas "ab + ab". Si vous échappez au +, cela correspond littéralement. Trouve donc grep -E "ab\+""ab + ab", mais pas "abbb".

Henning Kockerbeck
la source
1
Quel gâchis hérité ... ;-) comme la magie et la supermagie dans vim. Urgh. Le prix à payer pour la compatibilité descendante ...
Rmano