GNU/Linux >> Linux Esercitazione >  >> Linux

Cattura gruppi con Awk o Grep?

Vorrei scorrere ogni pattern trovato e avere accesso ai diversi gruppi di acquisizione all'interno del loop, possibilmente con grep o awk (Vorrei seguirli se possibile per evitare di impararne un terzo, ma se proprio necessario ne imparerò un altro!)

Fa qualcosa del tipo:

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

esiste?

Testo di esempio:

blah12687hello=123
nothingthatmatches
blah3211hello=123456
blah15butnottheotherpattern

Con il ciclo menzionato prima, dovrebbe produrre:

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

Risposta accettata:

Il bash shell di per sé fornisce un modo per eseguire il processo di corrispondenza delle espressioni regolari dei gruppi catturati come convenientemente necessario.

Il =~ operatore all'interno di un'espressione di prova tra parentesi quadre, [[ con la stringa di corrispondenza sul lato sinistro dell'operatore e l'espressione regolare come operando destro.

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

Se l'espressione corrisponde alla stringa, la parte corrispondente della stringa viene archiviata nel BASH_REMATCH array che può essere eseguito in loop per accedere ai singoli gruppi acquisiti. Lo stato di uscita è se l'espressione regolare corrisponde, 1 in caso contrario, e 2 se l'espressione non è valida.

Per quanto riguarda il tuo esempio, supponendo che tu abbia le righe di input memorizzate in un array e le parole blah e hello sono schemi fissi

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

Come puoi vedere nel codice sopra, una volta che abbiniamo l'espressione regolare per essere true, possiamo eseguire il loop del BASH_REMATCH array per stampare ciascuno dei gruppi acquisiti. L'output complessivo dello script sarebbe qualcosa del tipo

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.

Come puoi vedere il BASH_REMATCH[0] contiene sempre la parte della stringa che è stata abbinata con successo dalla regex e si può accedere ai singoli gruppi catturati dall'indice 1 avanti. Puoi scrivere una logica personalizzata per elaborare ciascuno dei gruppi acquisiti, che è ciò che intendevi fare originariamente.

Correlati:qual è il più portatile di sed, awk, perl e sh?

Se sei interessato a leggere un file di input, usa un while loop con reindirizzamento dell'input sul file da elaborare

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. Condivisione di gruppi supplementari con contenitori Podman

  2. Grep con operatori logici?

  3. Cattura i pacchetti con tcpdump

  4. grep:cattura di gruppo

  5. Come eseguire il grep dell'output di ps con le intestazioni

Modifica i gruppi in Linux con il comando groupmod

Elimina i gruppi in Linux con il comando groupdel

Crea nuovi gruppi in Linux con il comando Groupadd

Comandi di gestione dei gruppi in Linux

Comando Grep in Linux (con esempi)

10 esempi pratici di regex con grep