bash 正则表达式 多个匹配

bash 正则表达式 多个匹配

我有一个很好的小bash脚本,它解析正则表达式的消息并对捕获组执行某些操作:

regex='\((Closes|Resolves):\s([0-9]+)\)'
msg='Fixed a problem (Closes: 1234), (Resolves: 5678)'

if [[ $msg =~ $regex ]] ; then
  action="${BASH_REMATCH[1]}"
  issue="${BASH_REMATCH[2]}"
  do_something $action $issue
fi

这对于第一个匹配很有效,但如果有多个匹配msg,则后面的匹配将被忽略。有没有办法让我循环浏览每场比赛,或者是时候开始考虑pythonor 了perl

答案1

内置bash语法没有明确支持它,但可以通过一些变量替换和一些递归轻松实现。

function do_something {
  echo $1 $2
}

function handlematches {
  regex='\((Closes|Resolves):\s([0-9]+)\)'
  msg=$1

  if [[ $msg =~ $regex ]] ; then
    action="${BASH_REMATCH[1]}"
    issue="${BASH_REMATCH[2]}"
    do_something "$action" "$issue"

    # Remove the first regex match and try again
    handlematches "${msg/${BASH_REMATCH[0]}/}"
  fi
}

message='Fixed a problem (Closes: 1234), (Resolves: 5678)'
handlematches "$message"

输出:

Closes 1234
Resolves 5678

答案2

如同斯图尔特的回答,但使用迭代而不是递归方法:

regex='\((Closes|Resolves): ([0-9]+)\)'
msg='Fixed a problem (Closes: 1234), (Resolves: 5678)'

while [[ $msg =~ $regex ]]; do
        action=${BASH_REMATCH[1]}
        issue=${BASH_REMATCH[2]}
        do_something "$action" "$issue"

        msg=${msg/"${BASH_REMATCH[0]}"/}
done

这将迭代字符串,$msg直到正则表达式不再匹配。在每次迭代中,使用参数替换来删除匹配位bash

如果您想保留原始的$msg,请先在另一个变量中复制它。

do_something () {
        printf 'action=%s, issue=%s\n' "$1" "$2"
}

这输出

action=Closes, issue=1234
action=Resolves, issue=5678

相关内容