Группа захвата регулярных выражений Bash


22

Я пытаюсь сопоставить несколько буквенно-цифровых значений (это число может отличаться) из строки и сохранить их в массив группы захвата bash. Тем не менее, я получаю только первый матч:

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

Как видите, оно соответствует первому значению, которое я ищу, но не второму.


1
Будете ли вы довольствоваться циклическим выводом echo "$mystring1" | grep -oE '/instances/([A-Z0-9]+)'?
Джефф Шаллер

Ответы:


22

Жаль, что вы не можете выполнить глобальное сопоставление в bash. Ты можешь это сделать:

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

Это работает путем удаления префикса соответствия из строки, чтобы можно было сопоставить следующую часть. Он уничтожает строку, но в функции это локальная переменная, так что кого это волнует?

Я бы на самом деле использовал эту функцию для заполнения массива:

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

спасибо - это выглядит как жизнеспособное решение - проблема только в том, что в bash 3.2 не существует mapfile ...
Артур Лисенко

1
См. Mywiki.wooledge.org/BashFAQ/001 для альтернатив
Гленн Джекман

6

Чтобы получить второе значение массива, вам нужно иметь второй набор скобок в регулярном выражении:

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

Спасибо, но я ищу неизвестное количество возможных совпадений.
Артур Лисенко

1
Я проголосовал за ваш вопрос, потому что я также ожидал, что в массив войдут несколько совпадений, но, похоже, они не появятся, если только у вас на самом деле несколько наборов скобок.
Джефф Шаллер
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.