GNU/Linux >> Tutoriels Linux >  >> Linux

Capturer des groupes avec Awk ou Grep ?

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.

Connexe :Quel est le plus portable de sed, awk, perl et sh ?

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

Linux
  1. Capturer des paquets avec tcpdump

  2. Gérer les groupes d'utilisateurs Linux

  3. Gérer les groupes de sécurité et les règles

  4. grep :capture de groupe

  5. Utiliser grep contre awk

Modifier des groupes sous Linux avec la commande groupmod

Supprimer des groupes sous Linux avec la commande groupdel

Créer de nouveaux groupes sous Linux avec la commande Groupadd

Commandes de gestion de groupe sous Linux

Commande Grep sous Linux (avec exemples)

10 exemples pratiques de regex avec grep