Reputation: 23
I want to use Bash regex matching (with the =~ operator) to match a string which includes quotes. Say for example I have the following string and I want to extract the text between quotes:
foo='"Hello World!"'
My first try was to put the regex in strong quotes like so to force the quotes to be regular characters.
[[ "$foo" =~ '".*"' ]]
That fails because Bash interprets this as a string match rather than a regex.
Then I tried to escape the quotes with \ like so:
[[ "$foo" =~ \".*\" ]]
That fails (EDIT: Actually, it doesn't. It fails if there's no space between \" and ]] but the version here works just fine.) because the first \ is in plain bash text and fails to escape the quote (I think. The coloring in VIM indicates that the second quote is escaped but not the first and running the script fails).
So is there some way I can escape the " characters without transforming the regex match into a string match?
Upvotes: 2
Views: 15539
Reputation: 77079
Actually, your second attempt works for me in bash 3 and 4:
$ echo "$BASH_VERSION"
3.2.51(1)-release
$ echo "$foo"
"Hello World!"
$ [[ "$foo" =~ \".*\" ]] && echo $BASH_REMATCH
"Hello World!"
$ echo "$BASH_VERSION"
4.3.18(1)-release
$ echo "$foo"
"Hello World!"
$ [[ "$foo" =~ \".*\" ]] && echo "${BASH_REMATCH[0]}"
"Hello World!"
However, to talk theory for a second, it all has to do with how bash interprets the expression as a whole. As long as the regular-expression characters themselves aren't quoted, the rest of the expression can be quoted without side-effects:
$ [[ $foo =~ '"'.*'"' ]] && echo $BASH_REMATCH
"Hello World!"
but perhaps the easiest way of all is to use a second variable to hold the regex itself.
$ exp='".*"'
$ [[ $foo =~ $exp ]] && echo $BASH_REMATCH
"Hello World!"
Upvotes: 11