Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't string literals be used in bash regular expression tests?

Why does the following bash script only print out variable worked?

#! /bin/bash

foo=baaz
regex='ba{2}z'

if [[ $foo =~ 'ba{2}z' ]]; then
    echo "literal worked"
fi

if [[ $foo =~ $regex ]]; then
    echo "variable worked"
fi

Is there something in the bash documentation that states the =~ operator only works with variables, not literals? Does this limitation apply to any other operators?

like image 997
splicer Avatar asked Jul 12 '11 14:07

splicer


2 Answers

You don't need quotes for bash regex anymore:

#! /bin/bash

foo=baaz
regex='ba{2}z'

if [[ $foo =~ ba{2}z ]]; then
    echo "literal worked"
fi

if [[ $foo =~ $regex ]]; then
    echo "variable worked"
fi

# Should output literal worked, then variable worked

I can't remember which version changed this though.

like image 93
NorthGuard Avatar answered Sep 21 '22 08:09

NorthGuard


Your code actually works as expected up until Bash 3.1. But since Bash 3.2 the behavior of the pattern match operator has been changed. Quote from the latest Bash Manual:

“Any part of the pattern may be quoted to force it to be matched as a string.“

And that is exactly what is happening here. You meant to use {} as meta characters, but since you quoted it Bash interprets them literally. You have two options.:

1.You can turn on the 3.1 compatibility mode with shopt -s compat31 like this:

#!/bin/bash
shopt -s compat31

foo=baaz
regex='ba{2}z'

if [[ $foo =~ 'ba{2}z' ]]; then
    echo "literal worked"
fi

if [[ $foo =~ $regex ]]; then
    echo "variable worked"
fi

2.You can port your code, by removing the quotations from the right hand side of the operator:

#!/bin/bash

foo=baaz
regex='ba{2}z'

if [[ $foo =~ ba{2}z ]]; then
    echo "literal worked"
fi

if [[ $foo =~ $regex ]]; then
    echo "variable worked"
fi
like image 21
Ferenc Géczi Avatar answered Sep 22 '22 08:09

Ferenc Géczi