使用bash_rematch的Bash正则表达式未按预期捕获
我试图捕捉BAR_BAR在FOO_FOO_FOO_BAR_BAR使用正则表达式如下:(?:.*?_){3}(.*)。
正则表达式在使用 RegExr 或 regex101 等验证器时有效,但在我运行时 Bash 不返回任何内容:
text="FOO_FOO_FOO_BAR_BAR"
regex="(?:.*?_){3}(.*)"
[[ $text =~ $regex ]] && echo "${BASH_REMATCH[1]}"
当我运行以下示例正则表达式时,它运行良好(返回b):
text="abcdef"
regex="(b)(.)(d)e"
[[ $text =~ $regex ]] && echo "${BASH_REMATCH[1]}"
我是在 Bash 中使用正则表达式的新手,我在这里缺少什么?
回答
POSIX 正则表达式不支持非捕获组和惰性量词。Bash 使用 POSIX ERE,因此您可以使用
text="FOO_FOO_FOO_BAR_BAR"
regex="([^_]*_){3}(.*)"
[[ $text =~ $regex ]] && echo "${BASH_REMATCH[2]}"
# => BAR_BAR
这里,
([^_]*_){3}- 匹配任何零个或多个字符的三个出现(第 1 组),_后面跟一个_字符除外(.*)- 字符串的其余部分(第 2 组)。
在这种情况下,捕获组用于在开始时为分组构造提供服务,"${BASH_REMATCH[2]}"并保存所需的值。