it-swarm.com.de

Bash-Regex-Erfassungsgruppe

Ich versuche, mehrere alphanumerische Werte (diese Zahl kann variieren) von einer Zeichenfolge abzugleichen und sie in einem Bash-Capture-Gruppenarray zu speichern. Ich bekomme jedoch nur das erste Match:

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]}

Wie Sie sehen können, entspricht es dem ersten Wert, den ich suche, aber nicht dem zweiten.

23
Arthur Lyssenko

Es ist eine Schande, dass Sie in Bash kein globales Matching durchführen können. Du kannst das:

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

Dies funktioniert, indem das übereinstimmende Präfix von der Zeichenfolge entfernt wird, damit der nächste Teil abgeglichen werden kann. Es zerstört den String, aber in der Funktion ist es eine lokale Variable, also wen interessiert das?.

Ich würde diese Funktion tatsächlich verwenden, um ein Array zu füllen:

$ mapfile -t matches < <( global_rematch "$mystring1" "$regex" )
$ printf "%s\n" "${matches[@]}"
1BBBBBB
2AAAAAAA
26
glenn jackman

Um den zweiten Array-Wert zu erhalten, benötigen Sie einen zweiten Satz Klammern im regulären Ausdruck:

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
7
Jeff Schaller

Python-Implementierung:

def getall(mysentence):
    regex = re.compile(r'.*?/instances/([0-9A-Z]+)')
    result = regex.findall(mysentence)
    return result

print(getall('<link rel="self" href="/api/clouds/1/instances/1BBBBBB"/> dsf <link rel="self" href="/api/clouds/1/instances/2AAAAAAA"/>'))
0