Histoire de l'expansion de Bash

Y a-t-il une raison historique pour laquelle Bash "globbing" et expressions régulières ne sont pas identiques? Par exemple, je crois que dans Bash [1-2]* correspond tout ce qui commence par un 1 ou un 2 suivi de n'importe quoi d'autre, alors que comme une expression régulière [1-2]* correspondrait seulement une séquence de 1s et 2s. Mon script Bash et REGEX foo sont tous les deux assez faibles et je rencontre régulièrement des problèmes liés à ces différences qui me rendaient curieux de savoir pourquoi ils sont différents.

bash été initialement conçu à la fin des années 80 comme un clone partiel de ksh avec certaines fonctionnalités interactives de csh / tcsh.

Les origines de la globulation doivent être trouvées dans les coquilles antérieures sur lesquelles elle s'appuie.

ksh lui-même est une extension de la shell Bourne. La shell Bourne elle-même (sortie en 1979 sous Unix V7) était une mise en œuvre propre, mais ne partait pas complètement de la shell Thompson (la shell de V1 -> V6) et incorporait des caractéristiques de la shell de Mashey.

En particulier, les arguments de command étaient toujours séparés par des blancs, | était maintenant le nouvel opérateur de pipe mais ^ était toujours supporté comme alternative (et explique aussi pourquoi vous faites [!az] et non [^az] ), $1 était toujours le premier argument d'un script et l'antislash était toujours le caractère d'échappement. Un grand nombre des opérateurs regexp ( ^\|$ ) ont une signification particulière dans le shell.

Le shell de Thompson s'appuyait sur un utilitaire externe pour le globbing. Quand sh trouvé non guidé * , [ ou ? s dans la command, il exécuterait la command via glob .

 rm *.txt 

finirait par courir glob comme:

 ["glob", "rm", "*.txt"] 

et glob finirait par exécuter rm avec la list des files correspondant à ce model.

 grep a.\*b *.txt 

exécuterait glob comme:

 ["glob", "grep", "a.\252b", "*.txt"] 

Le * ci-dessus a été cité en définissant le 8ème bit sur ce caractère, empêchant glob de traiter cela comme un caractère générique. glob supprimerait alors ce bit avant d'appeler grep .

Pour faire l'équivalent avec des expressions rationnelles, cela aurait été:

 regexp rm '\.txt$' 

Ou:

 regexp rm '^[^.].*\.txt$' 

pour exclure les files point.

La nécessité d'échapper aux opérateurs car ils doublent comme des caractères spéciaux shell, le fait que . , commun dans les noms de files est un opérateur de regexp, il n'est pas très approprié de faire correspondre les noms de files et compliqué pour un débutant. Dans la plupart des cas, vous n'avez besoin que de caractères generics qui peuvent replace un ( ? ) Ou un nombre ( * ) de caractères.

Maintenant, différentes coquilles ont ajouté différents opérateurs de globulation. De nos jours, les globes ksh et zsh (et dans une certaine mesure bash -O extglob qui implémente un sous-set de ksh globs) sont fonctionnellement équivalents aux regexps avec une syntaxe less lourde à utiliser avec les noms de files et la syntaxe actuelle du shell. Par exemple, dans zsh (avec extension extendedglob), vous pouvez faire:

 echo a#.txt 

si vous voulez (peu probable) correspondre à des noms de files composés de séquences de a suivies de .txt . Plus facile que l' echo (^a*\.txt$) (ici utiliser des accolades pour isoler les opérateurs regex des opérateurs de shell qui auraient pu être unidirectionnels).

 echo (foo|bar|<1-20>).(#i)mpg 

Pour les files mpg (insensibles à la casse) dont le nom de base est foo, barre ou un nombre décimal de 1 à 20 …

ksh93 peut aussi incorporer des regexps (basic, extended, perl-like ou "augmented") dans ses globs (bien qu'il soit assez buggé) et fournit même un outil pour convertir entre glob et regexp ( printf %R , printf %P ):

 echo ~(Ei:.*\.txt) 

pour associer des files txt (non cachés) à des expressions rationnelles E xtended, de façon insensible.

Kleene a introduit des langues régulières en 1956. Le text séminal n'avait pas la notation moderne complète pour les expressions régulières, mais il a introduit l'écanvas Kleen: A* signifiant «n'importe quel nombre de répétitions de A ». Au cours de la prochaine décennie, des notations plus ou less standard sont apparues, en particulier . pour un caractère arbitraire et ? pour signifier que le caractère précédent est facultatif.

La notation globh de Bash découle de la command glob introduite tout le long du path dans Unix v1 en 1971. A l'époque, le globbing était exécuté par un programme séparé; il a ensuite été déplacé dans la coquille. La command early glob a ? pour signifier "n'importe quel caractère" et * pour signifier "n'importe quelle séquence de caractères". Je ne sais pas pourquoi les personnages ont été choisis; ? est assez intuitif et * peut avoir été inspiré de celui des expressions régulières.

Globbing n'était pas destiné à être aussi général que les expressions régulières, et les expressions régulières n'étaient pas très répandues à l'époque, donc il n'y avait pas d'appel pour unifier les concepts. Dès le début, il y avait des incompatibilités syntaxiques, avec ? , . et * signifiant différentes choses dans les templates de noms de files et dans les expressions régulières.

Les shells modernes tels que bash se développent sur des schémas de globes, mais c'est une évolution graduelle qui maintient la rétrocompatibilité. Ksh88 (la version 1988 du shell Korn ) introduisit une syntaxe étendue pour les patterns shell, qui ne pouvait pas être la même syntaxe que les expressions régulières habituelles mais qui en était fortement inspirée: *(PATTERN) signifie n'importe quel nombre de répétitions de PATTERN , @(PATTERN1|PATTERN2) signifie " PATTERN1 ou PATTERN2 ", etc.

Les versions modernes de bash (depuis 2.02) supportent les patterns étendus de ksh88, si vous shopt -s extglob premier.

Raison historique: OUI. Référence:
http://en.wikipedia.org/wiki/Glob_(programming)#Origin

Juste pour montrer la divergence, voici un exemple simple et bon: a*

  • shell globbing: le sens est, le premier caractère est a et puis tout ce que (a, ab, abca …)
  • regex: signification est, zéro ou plusieurs répétitions du caractère a (a, aa, aaa …)

Je conviendrais volontiers que cette divergence de sens est très déroutante pour les nouveaux users.

Globbing est peut-être plus facile à saisir pour les nouveaux arrivants, mais c'est aussi une construction less puissante.