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]+)'
杰夫·

4
也许值得一提的是著名的“不能用正则表达式解析HTML”
Digital Trauma 2015年

Answers:


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 ...
Arthur Lyssenko 2015年

1
有关替代方案,请参见mywiki.wooledge.org/BashFAQ/001
glenn jackman 2015年

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

谢谢,但是我希望与未知数量的可能匹配项进行匹配。
Arthur Lyssenko 2015年

1
我对您的Q表示赞成,因为我也希望将多个匹配项放入数组中,但除非您实际上有多组括号,否则它们似乎没有。
杰夫·谢勒
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.