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?

20
  • In your if condition shoudnt that $output be without quotes Commented Apr 24, 2016 at 3:43
  • @Manish tried that didnt work Commented Apr 24, 2016 at 3:49
  • check this :- ideone.com/c1ojBS its working Commented Apr 24, 2016 at 3:50
  • Yes it won't work because your regular expression is also not correct. What you actually want? Commented Apr 24, 2016 at 3:53
  • @Manish regex is correct as well as code is running..don't understand OP's problem Commented Apr 24, 2016 at 3:54

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.