Bash regex capture group

22

Saya mencoba mencocokkan beberapa nilai alfanumerik (angka ini dapat bervariasi) dari string dan menyimpannya ke array grup bash capture. Namun, saya hanya mendapatkan pertandingan pertama:

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

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

[[ $mystring1 =~ $regex ]]

echo ${BASH_REMATCH[1]}
1BBBBBB

echo ${BASH_REMATCH[2]}

Seperti yang Anda lihat - cocok dengan nilai pertama yang saya cari, tetapi tidak yang kedua.

Arthur Lyssenko
sumber
1
Apakah Anda puas dengan perulangan atas hasil echo "$mystring1" | grep -oE '/instances/([A-Z0-9]+)'?
Jeff Schaller
4
Mungkin layak disebut yang terkenal Anda tidak dapat menguraikan HTML dengan posting regex .
Digital Trauma

Jawaban:

22

Sayang sekali Anda tidak dapat melakukan pencocokan global dalam bash. Kamu bisa melakukan ini:

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

Ini bekerja dengan memotong awalan yang cocok dari string sehingga bagian selanjutnya dapat dicocokkan. Itu menghancurkan string, tetapi dalam fungsi itu adalah variabel lokal, jadi siapa yang peduli.

Saya benar-benar akan menggunakan fungsi itu untuk mengisi array:

$ mapfile -t matches < <( global_rematch "$mystring1" "$regex" )
$ printf "%s\n" "${matches[@]}"
1BBBBBB
2AAAAAAA
glenn jackman
sumber
terima kasih- ini sepertinya solusi-satunya masalah yang layak adalah mapfile tidak ada di bash 3.2 ...
Arthur Lyssenko
1
Lihat mywiki.wooledge.org/BashFAQ/001 untuk alternatif
glenn jackman
6

Untuk mendapatkan nilai array kedua, Anda harus memiliki set tanda kurung kedua di regex:

mystring1='<link rel="self" href="/unix//api/clouds/1/instances/1BBBBBB"/> dsf <link rel="self" href="/unix//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
Jeff Schaller
sumber
Terima kasih, di mana pun saya ingin mencocokkan dengan jumlah yang mungkin tidak cocok.
Arthur Lyssenko
1
Saya meningkatkan Q Anda karena saya juga mengharapkan beberapa kecocokan masuk ke dalam array, tetapi tampaknya tidak, kecuali jika Anda benar-benar memiliki beberapa set tanda kurung.
Jeff Schaller