Y a-t-il une raison historique pour laquelle le "globbing" de Bash et les 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 quoi que ce soit d'autre, alors qu'une expression régulière [1-2]*
ne correspondrait qu'à une séquence de 1 et de 2. Mes scripts Bash et REGEX foo sont tous deux assez faibles et je rencontre régulièrement des problèmes associés à ces différences qui m'ont rendu curieux de savoir pourquoi elles sont différentes.
shell
regular-expression
wildcards
history
StrongBad
la source
la source
rm -- ^[^.].*\.txt$
place derm -- *.txt
?find . -regex ".*\.txt$" | xargs rm --
ourename
pour renommer des fichiers (c'estsed
pour les noms de fichiers), méfiez-vous que certains systèmes ont un autrerename
.^[^.].*\.txt$
devait prendre en compte l'ignorance des fichiers dot. Notez que la-regex
est une extension de GNU, des coquilles comme ksh93 ou zsh peuvent incorporer des expressions rationnelles dans leurs petites boules (essayez par exemple:ksh93 -c 'echo ~(E:^[^.].*\.txt$)'
)Réponses:
bash
a été initialement conçu à la fin des années 80 comme un clone partiel deksh
certaines fonctionnalités interactives de csh / tcsh.Les origines du globbing doivent être trouvées dans les coquilles antérieures sur lesquelles il s'appuie.
ksh
lui-même est une extension du shell Bourne. Le shell Bourne lui-même (sorti pour la première fois en 1979 dans Unix V7) était une implémentation propre à partir de zéro, mais il ne s'écartait pas complètement du shell Thompson (le shell de V1 -> V6) et incorporait des fonctionnalités du shell Mashey.En particulier, les arguments de commande étaient toujours séparés par des blancs,
|
était désormais le nouvel opérateur de canal mais^
était toujours pris en charge comme alternative (et explique également pourquoi vous le faites[!a-z]
ou non[^a-z]
),$1
était toujours le premier argument d'un script et la barre oblique inverse était toujours le caractère d'échappement. . De nombreux opérateurs regexp (^\|$
) ont une signification particulière dans le shell.La coque Thompson s'appuyait sur un utilitaire externe pour la globulation. Une fois
sh
trouvé sans guillemets*
,[
ou?
s dans la commande, il exécuterait la commandeglob
.finirait par exécuter glob comme:
et glob finirait par fonctionner
rm
avec la liste des fichiers correspondant à ce modèle.se déroulerait
glob
comme:Ce qui
*
précède a été cité en définissant le 8e bit sur ce caractère, empêchantglob
de le traiter comme un caractère générique.glob
retirerait alors ce bit avant d'appelergrep
.Pour faire l'équivalent avec des expressions régulières, cela aurait été:
Ou:
pour exclure les fichiers dot.
La nécessité d'échapper aux opérateurs car ils se doublent de caractères spéciaux shell, le fait que
.
, commun aux noms de fichiers, est un opérateur regexp, il n'est pas très approprié de faire correspondre les noms de fichiers et compliqué pour un débutant. Dans la plupart des cas, vous n'avez besoin que de caractères génériques qui peuvent remplacer un (?
) ou n'importe quel nombre (*
) de caractères.Maintenant, différents shells ont ajouté différents opérateurs de globbing. De nos jours, les globes ksh et zsh (et dans une certaine mesure
bash -O extglob
qui implémentent un sous-ensemble de globes ksh) sont fonctionnellement équivalents aux regexps avec une syntaxe moins lourde à utiliser avec les noms de fichiers et la syntaxe shell actuelle. Par exemple, danszsh
(avec l'extension extendedglob), vous pouvez faire:si vous voulez (peu probable) faire correspondre les noms de fichiers composés de séquences
a
suivies de.txt
. Plusecho (^a*\.txt$)
simple que (ici, utiliser des accolades comme moyen d'isoler les opérateurs regex des opérateurs shell qui auraient pu être à sens unique pour les shells).Pour les fichiers mpg (insensibles à la casse) dont le nom de base est foo, bar ou un nombre décimal de 1 à 20 ...
ksh93
peut désormais incorporer des expressions rationnelles (de base, étendues, de type perl ou "augmentées") dans ses globes (bien que ce soit assez bogué) et fournit même un outil pour convertir entre glob et regexp (printf %R
,printf %P
):à match (non caché) txt fichiers avec E Xtended expressions régulières, crémerie- i nsensitively.
la source
~(opt:pat)
aucune des options capitalisées. Peut-êtreprint -r -- ~(Ei).*\.txt$
. Mettre le motif à l'intérieur ne semble utile que pour éviter d'avoir à activer ou désactiver une option pour une partie d'un motif. Curieusement, vous pouvez mélanger et assortir plusieurs langages de modèles dans le même glob.~(Ki)*.~(E)txt$
est équivalent. (Au final, tout est simplement converti en regex et passé au moteur de regex de libast en interne).~(Ei:.*\.txt)
fonctionne pour moi même avec des versions vieilles de 15 ans comme ksh93 o +.~(E)x
et~(E:x)
est que ce dernier est ancré (correspondx
uniquement sur tandis que l'ancien correspond à tout ce qui contientx
), ce qui peut être le type de problème que vous avez rencontré (utilisez~(-lr)~(E:x)
pour supprimer l'ancrage,~(E-lr:x)
ne fera pas). En tout cas, je suis d'accord, c'est assez buggé, même dans la dernière version.Les langues régulières ont été introduites par Kleene en 1956. Le papier séminal n'avait pas la notation moderne complète pour les expressions régulières, mais il a introduit "l'étoile de Kleen":
A*
ce qui signifie "n'importe quel nombre de répétitions deA
". Au cours de la décennie suivante, des notations plus ou moins standard sont apparues, en particulier.
pour un caractère arbitraire et?
pour signifier que le caractère précédent est facultatif.La notation de globbing de Bash découle de la
glob
commande introduite tout au long d' Unix v1 en 1971. À l'époque, le globbing était effectué par un programme distinct; il a ensuite été déplacé dans la coquille. La premièreglob
commande doit?
signifier «n'importe quel caractère» et*
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.Les globes n'étaient pas destinés à être aussi généraux que les expressions régulières, et les expressions régulières n'étaient pas très répandues à l'époque, il n'y avait donc aucun appel à unifier les concepts. Dès le début, il y avait des incompatibilités syntaxiques, avec
?
,.
et qui*
signifie des choses différentes dans les modèles de noms de fichiers et dans les expressions régulières.Les coques modernes telles que bash se développent sur des modèles globaux, mais c'était une évolution progressive maintenant la compatibilité descendante. Ksh88 (la version 1988 du shell Korn ) a introduit une syntaxe étendue pour les modèles de shell, qui ne pouvait pas être la même syntaxe que les expressions régulières habituelles mais qui s'en inspirait fortement:
*(PATTERN)
signifier n'importe quel nombre de répétitions dePATTERN
,@(PATTERN1|PATTERN2)
signifier «PATTERN1
ouPATTERN2
», etc.Les versions modernes de bash (depuis 2.02) prennent en charge les modèles étendus de ksh88, si vous émettez en
shopt -s extglob
premier.la source
extglob
option a été introduite dans bash 2.02 vers 1998. Zsh a acquisksh_glob
dans la série 3.1 quelque part à la même époque. Zsh a ses propres extensions globbing (certaines nécessitant l'extended_glob
option).bash
, contrairement àksh
, extglob rend bash non compatible POSIX car il n'est pas désactivé dans les variables. Dansksh
,var='@(*)'; echo $var
s'étend à tous les noms de fichiers dans le répertoire en cours qui commencent@(
et se terminent)
comme POSIX l'exige tandis que dansbash -O extglob
il s'étend à tous les fichiers. (encore, on peut considérer que le comportement bash a plus de sens ici (et le comportement ksh est assez pénible lorsque vous voulez avoir des modèles dans les variables)). Cette syntaxe de glob est si maladroite à cause de cela (compatibilité POSIX / Bourne). Comparez avec les globes étendus zsh.Raison historique: OUI. Référence:
http://en.wikipedia.org/wiki/Glob_(programming)#Origin
Juste pour montrer la divergence, voici un bon et simple exemple:
a*
a
et puis quoi que ce soit (a, ab, abca ...)a
(a, aa, aaa ...)Je conviens volontiers que cette divergence de sens est très déroutante pour les nouveaux utilisateurs.
La globalisation est peut-être plus facile à saisir pour les nouveaux arrivants, mais c'est aussi une construction moins puissante.
la source