bash_rematch和regex(带嵌套的parens)

时间:2015-12-05 21:45:25

标签: regex bash match

我在使用正则表达式时遇到问题,我需要搜索并删除与正则表达式匹配的模式,当发现我需要修剪时。我写了一个像这样的正则表达式

regex='(.*)((aa[[:space:]]bb)|(awd)|(bab)|(bc[[:space:]]d))(*.)'

其中我定义了所有的开头(1),其中可以是目标(2)的部分和所有结尾(3)。 使用简单的正则表达式(。)(abc)(。)很容易 串=" ABC&#34 ;;正则表达式='()(ABC)(。)'

[[ $string =~ $regex) && myvar=${BASH_REMATCH[2]} && buffer=${BASH_REMATCH[1]}${BASH_REMATCH[3]}

当我使用嵌套的parens和OR组定义正则表达式时就会出现问题,就像这里发布的第一个正则表达式一样。 这是我的shell中的一个示例:

$ string=" foo bar baz bac"
$ regex='(.*)((hello[[:space:]]world)|(example)|(funk[[:space:]]you)|(bar[[:space:]]baz))(.*)'

$ [[ $string =~ $regex ]] && echo ${BASH_REMATCH[1]}
foo
$ [[ $string =~ $regex ]] && echo ${BASH_REMATCH[2]}
bar baz
$ [[ $string =~ $regex ]] && echo ${BASH_REMATCH[3]}

$ [[ $string =~ $regex ]] && echo ${BASH_REMATCH[4]}

$ [[ $string =~ $regex ]] && echo ${BASH_REMATCH[5]}

$ [[ $string =~ $regex ]] && echo ${BASH_REMATCH[6]}
bar baz
$ [[ $string =~ $regex ]] && echo ${BASH_REMATCH[7]}
bac
$ [[ $string =~ $regex ]] && echo ${BASH_REMATCH[@]}
foo bar baz bac foo bar baz bar baz bac

匹配有一个奇怪的行为,我在$ {BASH_REMATCH [3]}中找不到输入字符串的另一部分,尽管它位于正则表达式的第3个parens中。 嵌套的parens会发生什么?

1 个答案:

答案 0 :(得分:1)

bash根据左括号的左右排序为捕获组分配数字。基本上,它是深度优先排序,而不是像你假设的那样广度优先。

1. (.*)
2. (
3.   (hello[[:space:]]world)|
4.   (example)|
5.   (funk[[:space:]]you)|
6.   (bar[[:space:]]baz)
   )
7. (.*)

在这个正则表达式中,组2基本上是3,4,5或6组中实际匹配的副本,因为组2不包含任何其他内容。第7组是您认为的第3个括号组。

第0组是整场比赛,它使用@解释了你的最后一行:

$ [[ $string =~ $regex ]] && echo ${BASH_REMATCH[@]}
foo bar baz bac foo bar baz bar baz bac
|             | | | |     | |     | | |
+-------------+ +-+ +-----+ +-----+ +-+
       0         1     2       6     7

(在分词过程中,空组3,4和5被作为空格吞噬。)