9

I have a nice little bash script which parses a message for a regular expression and does something with the capture groups:

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

This works well for the first match, but if there are multiple matches msg, later matches are ignored. Is there a way for me to loop through each match or is it time to start thinking of python or perl?

2 Answers 2

12

It's not explicitly supported by built-in bash syntax, but it can be easily achieved with a little variable substitution and some recursion.

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"

Output:

Closes 1234
Resolves 5678
3

Similar to Stewart's answer, but using an iterative rather than recursive approach:

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

This iterates over the string in $msg until the regular expression no longer matches. In each iteration, the matching bit is remove using a bash parameter substitution.

If you want to hold on to the original $msg, then make a copy of it in another variable first.

With

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

this outputs

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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .