我有一个很好的小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
,则后面的匹配将被忽略。有没有办法让我循环浏览每场比赛,或者是时候开始考虑python
or 了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