De recherche et de remplacement dans un bash en utilisant des expressions régulières
J'ai vu cet exemple:
hello=ho02123ware38384you443d34o3434ingtod38384day
echo ${hello//[0-9]/}
Qui suit la syntaxe suivante: ${variable//pattern/replacement}
Malheureusement, le pattern
champ ne semble pas en charge l'intégralité de la regex de la syntaxe (si j'utilise .
ou \s
, par exemple, il essaie de faire correspondre les caractères).
Comment puis-je rechercher/remplacer une chaîne de caractères à l'aide de regex complète de la syntaxe?
- Trouvé une question connexe ici: stackoverflow.com/questions/5658085/...
- Pour info,
\s
ne fait pas partie de la norme POSIX définit la syntaxe d'expression régulière (ni BRE ou ERE); c'est une extension PCRE, et surtout pas disponibles à partir du shell.[[:space:]]
est le plus universel équivalent. \s
peut être remplacé par[[:space:]]
, par la manière,.
par?
, et extglob extensions de la ligne de base du shell modèle de langage peut être utilisé pour des choses comme option sous-groupes, groupes répétés, et la comme.- Une description de Bash modèles.
- - Je l'utiliser dans bash version 4.1.11 sur Solaris... echo ${bonjour//[0-9]} Notez l'absence de la dernière barre oblique.
Vous devez vous connecter pour publier un commentaire.
Utilisation sed:
Remarque que l'
-e
's sont traitées dans l'ordre. Aussi, leg
drapeau de l'expression correspond à tous les événements de l'entrée.Vous pouvez aussi choisir votre outil préféré à l'aide de cette méthode, c'est à dire perl, awk, par exemple:
Ceci peut vous permettre de ne plus créatif matchs... Par exemple, dans la capture ci-dessus, les chiffres de remplacement ne seraient pas utilisés sauf s'il y a un match sur la première expression (en raison de paresseux
and
d'évaluation). Et bien sûr, vous avez le plein support de la langue de Perl pour faire votre appel d'offres...MYVAR
? La meilleure pratique est de sauver tous les majuscules pour les variables d'environnement shell et built-ins, évitant ainsi les conflits d'espace de noms.sed
ou d'autres outils externes est cher à cause de l'initialisation du processus de temps. J'ai particulièrement recherchées pour tous-bash solution, parce que j'ai trouvé à l'aide de bash substitutions à plus de 3x plus rapide que d'appelersed
pour chaque élément dans ma boucle.Ce fait peut être fait dans le plus pur bash:
...les rendements...
=~
est la clé. Mais un peu maladroit, compte tenu de la réaffectation dans la boucle. @jheddings solution 2 ans avant est une autre bonne option - appel sed ou perl).sed
ouperl
est judicieux, si l'utilisation de chaque invocation, pour traiter plus d'une seule ligne de saisie. L'invocation d'un tel outil à l'intérieur d'une boucle, par opposition à l'aide d'une boucle de traitement des flux de sortie, est irresponsable.$match
au lieu de$BASH_REMATCH
. (Vous pouvez la faire se comporter comme bash avecsetopt bash_rematch
.)$'\n'
fonctionne pour moi (tm).pattern='(['$'\n''])'
est juste un inutilement bavard façon d'écrirepattern=$'([\n])'
. Non pas que je suis sûr de savoir pourquoi vous avez parens ou le corset d'expression que ce soit;[[ $some_var =~ $'\n' ]]
fonctionne très bien comme elle est.spellcheck(1)
. Ou des scripts qui souhaitent avoir moins de dépendance. Je n'en conviennent autrement.spellcheck
? Parce queshellcheck
n'a pas de problème avec[[ $some_var =~ $'\n' ]]
-- qui n'a pas de dépendances autres que bash 3.2 ou version ultérieure; même Apple, l'expédition d'un ancien pré-GPLv3 libération, prévoit que.Ces exemples fonctionnent aussi dans bash pas besoin d'utiliser sed:
vous pouvez également utiliser le caractère de classe de support des expressions
sortie
Ce que @Lanaru voulais savoir, cependant, si je comprends correctement à la question, est pourquoi le "plein" ou PCRE extensions
\s\S\w\W\d\D
etc ne fonctionnent pas pris en charge dans php, ruby, python, etc Ces extensions sont de Perl-compatible regular expressions (PCRE) et peuvent ne pas être compatibles avec d'autres formes de coque à base d'expressions régulières.Ce n'est pas le travail:
de sortie avec tous les littérale "d" supprime les caractères de
mais la suivante ne fonctionne pas comme prévu
sortie
Espoir qui clarifie les choses un peu plus, mais si vous n'êtes pas confus encore, pourquoi ne pas vous essayer sur Mac OS X qui a la REG_ENHANCED indicateur activé:
Sur la plupart des saveurs de *nix, vous ne verrez que la sortie suivante:
nJoy!
${foo//$bar/$baz}
est pas POSIX.2 REP ERE ou la syntaxe -- c'est fnmatch()-style de pattern matching.${hello//[[:digit:]]/}
fonctionne, si nous voulions pour filtrer uniquement des chiffres précédés de la lettreo
,${hello//o[[:digit:]]*}
aurait un tout autre comportement que l'on attendait (puisque dans fnmatch modèles,*
correspond à tous les caractères, plutôt que de modifier les immédiatement avant l'élément à 0 ou plus).[[ $foo =~ $bar ]]
(qui, vous pouvez le constater, j'ai utilisé dans ma réponse) est ERE, mais${foo//$bar/$baz}
ne l'est pas.[0-9]
ou[[:digit:]]
Si vous faites des appels répétés et sont soucieux de performances, Ce test révèle la fête de la méthode est d'environ 15x plus rapide que la bifurcation pour le sed et d'autres processus externe.
Utilisation
[[:digit:]]
(notez le double crochets) selon le modèle:Voulais juste résumer les réponses (surtout @nickl-'s https://stackoverflow.com/a/22261334/2916086).