Pourquoi certaines commandes regex ont-elles des interprétations opposées de '\' avec différents caractères?

10

Prenez, par exemple, cette commande:

find . -regex ".*\.\(cpp\|h\)"

Cela trouvera tous les fichiers .h et .cpp dans votre répertoire. Le caractère de période '.' dans les expressions régulières signifie généralement "n'importe quel caractère". Pour qu'il ne corresponde qu'à une période réelle, vous devez l'échapper en utilisant la barre oblique inverse "\".

Dans ce cas, étant donné un caractère avec une signification spéciale, vous devez lui échapper pour obtenir le caractère réel qu'il représente.

Maintenant, prenez la parenthèse et la barre "ou", étant les caractères '(', ')' et '|', respectivement. Celles-ci ont également des significations spéciales, utilisées pour regrouper les expressions régulières. Cependant, pour obtenir la signification spéciale, les caractères doivent être échappés à l'aide de la barre oblique inverse! Sans la barre oblique inverse, les caractères ont la signification du caractère réel qu'ils représentent.

Pourquoi est-ce que '.' traité différemment de '(', ')' et '|'?

Cory Klein
la source

Réponses:

12

La réponse est vraiment "juste parce que". Il y a tout un tas de syntaxes d'expression régulière différentes, et bien qu'elles partagent une apparence similaire et que les bases sont généralement les mêmes, elles varient dans les détails.

Historiquement, chaque outil avait sa propre nouvelle implémentation, faisant ce que l'auteur pensait le mieux. Il y a un équilibre entre rendre les personnages spéciaux avec et sans échapper - trop de personnages qui sont "naturellement spéciaux" et vous finissez par devoir les échapper tout le temps juste pour les assortir; ou, dans l'autre sens, vous finissez par avoir besoin d'un tas d'évasions pour utiliser la syntaxe regex commune comme le regroupement (). Et tous ceux qui écrivaient un programme ont décidé comment le faire en fonction des besoins de leur programme, de ce qu'ils considéraient comme la bonne approche et de la phase de la lune.

Il y a une tentative de standardisation de POSIX, qui définit les " expressions régulières de base " et les " expressions régulières étendues ". De façon impressionnante, ceux-ci fonctionnent à l'envers les uns des autres en ce qui concerne \- parfois , mais pas avec une cohérence parfaite.

Les expressions régulières Perl sont devenues un autre standard de facto, pour deux raisons: premièrement, elles sont très flexibles et puissantes, et deuxièmement, elles sont en fait assez saines , avec des conventions comme "\ échappe toujours un caractère non alphanumérique".

GNU Find a une -regextypeoption, où vous pouvez changer la syntaxe d'expression régulière utilisée. Malheureusement, "perl" n'est pas une option, du moins dans la version de find que j'ai. (La valeur par défaut est, sans surprise, de GNU, "emacs", et cette syntaxe est documentée ici .)

mattdm
la source