Rechercher et remplacer dans bash en utilisant des expressions régulières

J’ai vu cet exemple:

hello=ho02123ware38384you443d34o3434ingtod38384day echo ${hello//[0-9]/} 

Qui suit cette syntaxe: ${variable//pattern/replacement}

Malheureusement, le champ pattern ne semble pas prendre en charge la syntaxe regex complète (si j’utilise . Ou \s , par exemple, il essaye de faire correspondre les caractères littéraux).

Comment puis-je rechercher / remplacer une chaîne en utilisant la syntaxe complète des expressions rationnelles?

Utilisez sed :

 MYVAR=ho02123ware38384you443d34o3434ingtod38384day echo $MYVAR | sed -e 's/[a-zA-Z]/X/g' -e 's/[0-9]/N/g' # prints XXNNNNNXXXXNNNNNXXXNNNXNNXNNNNXXXXXXNNNNNXXX 

Notez que les -e suivants sont traités dans l’ordre. De plus, l’indicateur g de l’expression correspondra à toutes les occurrences de l’entrée.

Vous pouvez également choisir votre outil préféré en utilisant cette méthode, par exemple perl, awk, par exemple:

 echo $MYVAR | perl -pe 's/[a-zA-Z]/X/g and s/[0-9]/N/g' 

Cela peut vous permettre de faire plus de correspondances créatives … Par exemple, dans le snip ci-dessus, le remplacement numérique ne serait utilisé que s’il y avait une correspondance sur la première expression (due à lazy and évaluation). Et bien sûr, vous avez la prise en charge linguistique complète de Perl pour faire vos enchères …

Cela peut être fait en pure bash:

 hello=ho02123ware38384you443d34o3434ingtod38384day re='(.*)[0-9]+(.*)' while [[ $hello =~ $re ]]; do hello=${BASH_REMATCH[1]}${BASH_REMATCH[2]} done echo "$hello" 

… cède …

 howareyoudoingtodday 

Ces exemples fonctionnent également en bash pas besoin d’utiliser sed:

 #!/bin/bash MYVAR=ho02123ware38384you443d34o3434ingtod38384day MYVAR=${MYVAR//[a-zA-Z]/X} echo ${MYVAR//[0-9]/N} 

vous pouvez également utiliser les expressions de parenthèses de classes

 #!/bin/bash MYVAR=ho02123ware38384you443d34o3434ingtod38384day MYVAR=${MYVAR//[[:alpha:]]/X} echo ${MYVAR//[[:digit:]]/N} 

sortie

 XXNNNNNXXXXNNNNNXXXNNNXNNXNNNNXXXXXXNNNNNXXX 

Ce que @Lanaru voulait savoir cependant, si je comprends bien la question, c’est pourquoi les extensions “complètes” ou PCRE \s\S\w\W\d\D etc. ne fonctionnent pas comme supscopes dans php ruby ​​python etc. les extensions proviennent d’expressions régulières compatibles Perl (PCRE) et peuvent ne pas être compatibles avec d’autres formes d’expressions régulières basées sur un shell.

Celles-ci ne fonctionnent pas:

 #!/bin/bash hello=ho02123ware38384you443d34o3434ingtod38384day echo ${hello//\d/} #!/bin/bash hello=ho02123ware38384you443d34o3434ingtod38384day echo $hello | sed 's/\d//g' 

sortie avec tous les caractères “d” littéraux supprimés

 ho02123ware38384you44334o3434ingto38384ay 

mais ce qui suit fonctionne comme prévu

 #!/bin/bash hello=ho02123ware38384you443d34o3434ingtod38384day echo $hello | perl -pe 's/\d//g' 

sortie

 howareyoudoingtodday 

J’espère que cela clarifie les choses un peu plus, mais si vous n’êtes pas encore confus, pourquoi ne pas essayer ceci sur Mac OS X, avec l’indicateur REG_ENHANCED activé:

 #!/bin/bash MYVAR=ho02123ware38384you443d34o3434ingtod38384day; echo $MYVAR | grep -o -E '\d' 

Sur la plupart des variantes de * nix, vous ne verrez que la sortie suivante:

 d d d 

nJoy!

Utilisez [[:digit:]] (notez les doubles crochets) comme motif:

 $ hello=ho02123ware38384you443d34o3434ingtod38384day $ echo ${hello//[[:digit:]]/} howareyoudoingtodday 

Je voulais juste résumer les réponses (en particulier @ https://stackoverflow.com/a/22261334/2916086 ).

Si vous effectuez des appels répétés et que vous êtes concerné par les performances, ce test révèle que la méthode BASH est environ 15 fois plus rapide que la conversion en sed et probablement en tout autre processus externe.

 hello=123456789X123456789X123456789X123456789X123456789X123456789X123456789X123456789X123456789X123456789X123456789X P1=$(date +%s) for i in {1..10000} do echo $hello | sed s/X//g > /dev/null done P2=$(date +%s) echo $[$P2-$P1] for i in {1..10000} do echo ${hello//X/} > /dev/null done P3=$(date +%s) echo $[$P3-$P2]