Grupo de captura de regex Bash

12

Estou tentando corresponder vários valores alfanuméricos (esse número pode variar) de uma string e salvá-los em uma matriz de grupo de captura bash. No entanto, só estou recebendo o primeiro jogo:

mystring1='<link rel="self" href="/api/clouds/1/instances/1BBBBBB"/> dsf <link rel="self" href="/api/clouds/1/instances/2AAAAAAA"/>'

regex='/instances/([A-Z0-9]+)'

[[ $mystring1 =~ $regex ]]

echo ${BASH_REMATCH[1]}
1BBBBBB

echo ${BASH_REMATCH[2]}

Como você pode ver, ele corresponde ao primeiro valor que estou procurando, mas não ao segundo.

    
por Arthur Lyssenko 22.12.2015 / 22:08

2 respostas

15

É uma pena que você não possa fazer uma correspondência global no bash. Você pode fazer isso:

global_rematch() { 
    local s=$1 regex=$2 
    while [[ $s =~ $regex ]]; do 
        echo "${BASH_REMATCH[1]}"
        s=${s#*"${BASH_REMATCH[1]}"}
    done
}
global_rematch "$mystring1" "$regex" 
1BBBBBB
2AAAAAAA

Isso funciona cortando o prefixo correspondente da string para que a próxima parte possa ser correspondida. Ele destrói a string, mas na função é uma variável local, então quem se importa.

Eu realmente usaria essa função para preencher uma matriz:

$ mapfile -t matches < <( global_rematch "$mystring1" "$regex" )
$ printf "%s\n" "${matches[@]}"
1BBBBBB
2AAAAAAA
    
por 22.12.2015 / 23:05
2

Para obter o segundo valor de matriz, você precisa ter um segundo conjunto de parênteses no regex:

mystring1='<link rel="self" href="/api/clouds/1/instances/1BBBBBB"/> dsf <link rel="self" href="/api/clouds/1/instances/2AAAAAAA"/>'

regex='/instances/([A-Z0-9]+).*/instances/([A-Z0-9]+)'

[[ $mystring1 =~ $regex ]]

$ echo ${BASH_REMATCH[1]}
1BBBBBB
$ echo ${BASH_REMATCH[2]}
2AAAAAAA
    
por 22.12.2015 / 22:23