1

So I have this code

function test(){
  local output="ASD[test]"
  if [[ "$output" =~ ASD\[(.*?)\] ]]; then
     echo "success";
  else
     echo "fail"
  fi;
}

And as you can see it's supposed to echo success since the string matches that regular expression. However this ends up returning fail. What did I do wrong?

Uzbekjon
  • 11,655
  • 3
  • 37
  • 54

1 Answers1

5

The ? in ASD\[(.*?)\] doesn't belong there. It looks like you're trying to apply a non-greedy modifier to the *, which is *? in Perl-compatible syntax, but Bash doesn't support that. (See the guide here.) In fact, if you examine $? after the test, you'll see that it's not 1 (the normal "string didn't match" result) but 2, which indicates a syntax error in the regular expression.

If you use the simpler pattern ASD\[(.*)\], then the match will succeed. However, if you use that regex on a string which might have later instances of brackets, too much will get captured by the parentheses. For example:

output=ASD[test1],ASD[test2]
[[ $output =~ ASD\[(.*)\] ]] && echo "first subscript is '${BASH_REMATCH[1]}'"
#=> first subscript is 'test1],ASD[test2'

In languages that support the *? syntax, it makes the matching "non-greedy" so that it will match the smallest string it can that makes the overall match succeed; without the ?, such expressions always match the longest possible instead. Since Bash doesn't have non-greediness, your best bet is probably to use a character class that matches everything except a close bracket, making it impossible for the match to move past the first one:

[[ $output =~ ASD\[([^]]*)\] ]] && echo "first subscript is '${BASH_REMATCH[1]}'"
#=> first subscript is 'test1'

Note that this breaks if there are any nested layers of bracket pairs within the subscript brackets - but then, so does the *? version.

Mark Reed
  • 91,912
  • 16
  • 138
  • 175