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.
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