J'aimerais boucler sur chaque motif trouvé et avoir accès aux différents groupes de capture à l'intérieur de la boucle, éventuellement avec grep
ou awk
(J'aimerais rester avec eux si possible pour éviter d'en apprendre un 3ème, mais si c'est vraiment nécessaire, j'en apprendrai un autre !)
Fait quelque chose comme :
awk-or-grep -E '(blah(.*)hello=(.*))' sampletext | while read -r l; do
echo $0 #1st capture group
echo $1 #2nd catpure group
dosomethingwith $2 #3rd capture group
done
existe ?
Exemple de texte :
blah12687hello=123
nothingthatmatches
blah3211hello=123456
blah15butnottheotherpattern
Avec la boucle mentionnée précédemment, elle devrait afficher :
blah12687hello=123
12687
<it should run the command dosomethingwith 123>
blah3211hello=123456
3211
<it should run the command dosomethingwith 123456>
Réponse acceptée :
Le bash
shell en lui-même fournit un moyen de faire correspondre les expressions régulières aux groupes capturés selon les besoins.
Le =~
opérateur dans une expression de test entre crochets doubles, [[
avec la chaîne de correspondance sur le côté gauche de l'opérateur et l'expression régulière comme opérande de droite.
if [[ "$str" =~ $re ]]; then
Si l'expression correspond à la chaîne, la partie correspondante de la chaîne est stockée dans le BASH_REMATCH
tableau qui peut être bouclé pour accéder aux groupes capturés individuels. Le statut de sortie est si l'expression régulière correspond,
1
si ce n'est pas le cas, et 2
si l'expression n'est pas valide.
En ce qui concerne votre exemple, en supposant que vous avez les lignes d'entrée stockées dans un tableau et les mots blah
et hello
sont des modèles fixes
#!/usr/bin/env bash
exampleStr=('blah12687hello=123' 'nothingthatmatches' 'blah3211hello=123456' 'blah15butnottheotherpattern')
re='blah([[:digit:]]+)hello=([[:digit:]]+)'
for str in "${exampleStr[@]}"; do
if [[ "$str" =~ $re ]]; then
for group in "${BASH_REMATCH[@]}"; do
printf "%s\n" "$group"
done
else
printf "No match \n"
fi
done
Comme vous pouvez le voir dans le code ci-dessus, une fois que nous correspondons à la regex pour être vraie, nous pouvons boucler sur le BASH_REMATCH
array pour imprimer chacun des groupes capturés. La sortie globale du script serait quelque chose comme
blah12687hello=123 # Value of BASH_REMATCH[0]
12687 # Value of BASH_REMATCH[1]
123 # Value of BASH_REMATCH[2]
Regex not matches.
blah3211hello=123456
3211
123456
Regex not matches.
Comme vous pouvez le voir, le BASH_REMATCH[0]
contient toujours la partie de la chaîne qui a été mise en correspondance avec succès par la regex, et les groupes individuels capturés sont accessibles à partir de l'index 1
en avant. Vous pouvez écrire une logique personnalisée pour traiter chacun des groupes capturés, ce que vous aviez initialement prévu de faire.
Si vous souhaitez lire une entrée de fichier, utilisez simplement un while
boucle avec redirection des entrées sur le fichier à traiter
while IFS= read -r line; do
if [[ "$line" =~ $re ]]; then
for group in "${BASH_REMATCH[@]}"; do
printf "%s\n" "$group"
done
else
printf "No match \n"
fi
done < inputFile.txt