Pourquoi «[az] *» correspond-il aux chaînes non alphabétiques?

9

J'ai un fichier alphanumavec ces deux lignes:

123 abc
this is a line

Je ne comprends pas pourquoi, lorsque je cours sed 's/[a-z]*/SUB/' alphanum, j'obtiens la sortie suivante:

SUB123 abc
SUB is a line

Je m'attendais à:

123 SUB
SUB is a line

J'ai trouvé un correctif (utilisez sed 's/[a-z][a-z]*/SUB/'plutôt), mais je ne comprends pas pourquoi cela fonctionne et le mien ne fonctionne pas.

Pouvez-vous m'aider?

Fakher Mokadem
la source
@Kamaraj, celui-ci est similaire, mais il y a la confusion entre les modèles de shell et les regex (et les réponses se concentrent sur le premier, car c'est ce ls foo*qu'il utilise). Mais de toute façon, si vous trouvez des questions en double, je pense que vous devriez également pouvoir les signaler comme telles.
ilkkachu
consultez regexr.com pour les visuels en direct et explique
RozzA
@RozzA Notez que le site Web auquel vous vous connectez prend en charge les expressions régulières Javascript et Perl, pas les expressions régulières POSIX.
Kusalananda

Réponses:

28

Le modèle [a-z]*correspond à zéro ou plusieurs caractères de la plage aà z(les caractères réels dépendent des paramètres régionaux actuels). Il n'y a aucun de ces caractères au tout début de la chaîne 123 abc(c'est-à-dire que le motif correspond), et également quatre d'entre eux au début de this is a line.

Si vous avez besoin d'au moins une correspondance, utilisez [a-z][a-z]*ou [a-z]\{1,\}, ou activez les expressions régulières étendues avec sed -Eet utilisez [a-z]+.

Pour visualiser où le motif correspond, ajoutez des parenthèses autour de chaque correspondance:

$ sed 's/[a-z]*/(&)/' file
()123 abc
(this) is a line

Ou, pour voir tous les matchs sur les lignes:

$ sed 's/[a-z]*/(&)/g' file
()1()2()3() (abc)
(this) (is) (a) (line)

Comparez ce dernier résultat avec

$ sed -E 's/[a-z]+/(&)/g' file
123 (abc)
(this) (is) (a) (line)
Kusalananda
la source
7
Techniquement [a-z]matches de collationner des éléments qui peuvent être faits de plus d'un caractère. Par exemple, dans certaines localités hongroises, les [a-z]matchs ont lieudzs
Stéphane Chazelas
12

Parce que *correspond à zéro ou plusieurs répétitions de l'atome précédent, et tous les moteurs d'expression régulière tentent de trouver la première correspondance. Il y a une sous-chaîne d'exactement zéro lettres au début de votre chaîne, c'est donc là qu'elle correspond. Dans le cas où la chaîne commence par une lettre, les *correspond autant que possible, mais cela est secondaire pour trouver la correspondance la plus à gauche.

Les correspondances de longueur nulle peuvent être un peu problématiques, et comme vous l'avez vu, la solution est de modifier le modèle de sorte qu'il nécessite au moins un caractère. Avec des expressions régulières étendues, vous pourriez +pour cela:sed -E 's/[a-z]+/SUB/'

Pour le plaisir, essayez:

echo 'less than 123 words' | sed 's/[0-9]*/x/g'
ilkkachu
la source