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一致は無視されます。各ゲームを循環する方法はありますか?それとも今考え始める時間pythonですか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

関連情報