GNU/Linux >> Tutoriales Linux >  >> Linux

¿Capturar grupos con Awk o Grep?

Me gustaría recorrer cada patrón encontrado y tener acceso a los diferentes grupos de captura dentro del ciclo, posiblemente con grep o awk (Me gustaría quedarme con ellos si es posible para evitar aprender un tercero, pero si es realmente necesario, ¡aprenderé otro!)

Hace algo como:

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?

Texto de muestra:

blah12687hello=123
nothingthatmatches
blah3211hello=123456
blah15butnottheotherpattern

Con el ciclo mencionado anteriormente, debería generar:

blah12687hello=123
12687
<it should run the command dosomethingwith 123>
blah3211hello=123456
3211
<it should run the command dosomethingwith 123456>

Respuesta aceptada:

El bash Shell por sí mismo proporciona una manera de hacer que el proceso de coincidencia de expresiones regulares de los grupos capturados sea convenientemente necesario.

El =~ operador dentro de una expresión de prueba de corchetes dobles, [[ con la cadena de coincidencia en el lado izquierdo del operador y la expresión regular como el operando derecho.

if [[ "$str" =~ $re ]]; then

Si la expresión coincide con la cadena, la parte coincidente de la cadena se almacena en el BASH_REMATCH matriz que se puede recorrer para acceder a los grupos capturados individuales. El estado de salida es si la expresión regular coincide, 1 si no es así, y 2 si la expresión no es válida.

En lo que respecta a su ejemplo, suponiendo que tiene las líneas de entrada almacenadas en una matriz y las palabras blah y hello son patrones fijos

#!/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

Como puede ver en el código anterior, una vez que hacemos coincidir la expresión regular para que sea verdadera, podemos recorrer el BASH_REMATCH matriz para imprimir cada uno de los grupos capturados. El resultado general del script sería algo como

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.

Como puede ver el BASH_REMATCH[0] siempre contiene la parte de la cadena que coincidió correctamente con la expresión regular, y se puede acceder a los grupos capturados individuales desde el índice 1 adelante. Puede escribir una lógica personalizada para procesar cada uno de los grupos capturados, que es lo que originalmente pretendía hacer.

Relacionado:¿Cuál es el más portátil de sed, awk, perl y sh?

Si está interesado en leer una entrada de archivo, simplemente use un while bucle con redirección de entrada en el archivo a procesar

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. Compartir grupos complementarios con contenedores Podman

  2. Grep con operadores lógicos?

  3. Administrar grupos de usuarios de Linux

  4. Administrar grupos y reglas de seguridad

  5. Usando grep vs awk

Modificar grupos en Linux con el comando groupmod

Eliminar grupos en Linux con el comando groupdel

Crear nuevos grupos en Linux con el comando Groupadd

Comandos de gestión de grupos en Linux

Comando Grep en Linux (con ejemplos)

10 ejemplos prácticos de expresiones regulares con grep