This question already has answers here:
Why isn't this regular expression test working? [duplicate]
(3 answers)
Closed 9 years ago.
I need to ensure a variable passed to my shell script matches a certain pattern.
var x has to be in the form of AA-X.X.XX (ie AA-1.2.33). If it doesn't match I need to exit.
Any ideas?
Bash has direct support for regular expressions.
if ! [[ $mystring ~= $pattern ]]; then
exit
fi
Use Bash's Double-Bracket Regex Tests
See Conditional Constructs in the GNU Bash Manual for a complete explanation of the =~ binary operator. As an example:
good_string='AA-1.2.33'
bad_string='BB.11.222.333'
regex='^AA-[[:digit:]]\.[[:digit:]]\.[[:digit:]][[:digit:]]$'
[[ "$good_string" =~ $regex ]]
echo $? # 0
[[ "$bad_string" =~ $regex ]]
echo $? # 1
Doable directly in bash
var=AA-1.2.33
[[ $var =~ ^AA-.\..\...$ ]]
echo $?
0
var=AA-1.2.3355
[[ $var =~ ^AA-.\..\...$ ]]
echo $?
1
Related
This question already has answers here:
bash regex with quotes?
(5 answers)
Closed 4 years ago.
I have a Regex that I got to work in a sed search/replace line, but I can't get the Regex to work in an If-Then-Else.
This is my sed line:
YELLOW="\033[1;33m"
OUTPUT[0]="$YELLOW ==================================+==================================="
cLEN=${OUTPUT[0]}
cLEN="$(echo $cLEN | sed 's/\\[[:digit:]]\+\[[[:digit:]];[[:digit:]]\+m//g')"
However now I am trying to make an if condition and I can't get the syntax right. I need it to evaluate from the beginning of the line $cLEN
if [[ $cLEN =~ '^\\[[:digit:]]\+\[[[:digit:]];[[:digit:]]\+m\s' ]]; then
echo true
else
echo error
exit 1
fi
When the right-hand side of =~ is quoted, it's treated as a literal string to match, not a regex.
Store your regex in a variable, then leave the reference to that variable unquoted on the right-hand side of the expression.
re='^\\[[:digit:]]+\[[[:digit:]];[[:digit:]]+m'
[[ $cLEN =~ $re ]]; echo $?
This question already has answers here:
How can I match spaces with a regexp in Bash?
(4 answers)
Closed 5 years ago.
I saw in bash regex match string that I should compare regexes with =~.
Tried the following:
if [[ "____[9 / 101] Linking" =~ "[0-9]*" ]]; then echo "YES"; fi
And nothing is printed...
Tried without the quotes:
if [[ "____[9 / 101] Linking" =~ [0-9]* ]]; then echo "YES"; fi
And it works fine. But what to do if my regex contains white spaces (quotes required)?
Put your regex in a variable. You are free to use quotes when defining the variable:
$ re="[0-9]*" ; [[ "____[9 / 101] Linking" =~ $re ]] && echo "YES"
YES
$ re="9 /" ; [[ "____[9 / 101] Linking" =~ $re ]] && echo "YES"
YES
Since the reference to $re inside [[...]] is unquoted, the value of $re is treated as a regex. Anything on the right-side of =~ that is quoted, however, will be treated as a literal string.
Notes
In regular expressions, as opposed to globs, * means zero or more of the preceding. Thus [0-9]* is considered a match even if zero characters are matching:
$ re="[0-9]*" ; [[ "____[a / bcd] Linking" =~ $re ]] && echo "YES"
YES
$ re="[0-9]" ; [[ "____[a / bcd] Linking" =~ $re ]] && echo "YES"
$
If you want to match one or more digits, use [0-9]+.
Precede the whitespace with a \:
if [[ "____[9 / 101] Linking" =~ [0-9]*\ /\ [0-9]* ]]; then echo "YES"; fi
This question already has answers here:
How to match digits in regex in bash script
(2 answers)
Closed 6 years ago.
I'm trying to play with regular expressions in bash but i can't understand why this follow scenario doesn't work :
Regexp:
REGEXP="^(test\/)(([a-zA-Z]+)\-)+(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$"
String:
STRING="test/test-ods-1.10.1"
Test:
if [[ "$STRING" =~ $REGEXP ]]
then
echo "match!"
else
echo "don't match"
fi
Normally in this scenario I should receive a "match" but it's always returning a "doesn't match".
\d is not defined in bash regexps. Replace them with [0-9] and it'll work :
$ [[ "test/test-1.10.1" =~ ^(test\/)(([a-zA-Z]+)\-)+(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$ ]]; echo $?
1
$ [[ "test/test-1.10.1" =~ ^(test\/)(([a-zA-Z]+)\-)+(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$ ]]; echo $?
0
No shorthand classes are defined in POSIX, and GNU extensions only bring a few of them, \w, \W, \s and \S according to regular-expressions.info.
In a server with bash version 3 I do this:
bash3$ e="tar xfz"; [[ "$e" =~ "^tar" ]] && echo 0 || echo 1
0
But when I execute the same command in bash version 4
bash4$ e="tar xfz"; [[ "$e" =~ "^tar" ]] && echo 0 || echo 1
1
I tried it in CentOS, Fedora and Ubuntu and got the same results. What is wrong?
Quoting the section on regular expressions from Greg's Wiki:
Before 3.2 it was safe to wrap your regex pattern in quotes but this has changed in 3.2. Since then, regex should always be unquoted.
This is the most compatible way of using =~:
e='tar xfz'
re='^tar'
[[ $e =~ $re ]] && echo 0 || echo 1
This should work on both versions of bash.
In this case, where you just want to make sure that your parameter starts with tar, you don't need regular expression matching, simple pattern matching works as well:
e='tar xfz'
[[ $e == tar* ]] && echo 0 || echo 1
I have a value in a variable that may be absolute or relative url, and I need to check which one it is.
I have found that there's a =~ operator in [[, but I can't get it to work. What am I doing wrong?
url="http://test"
if [[ "$url" =~ "^http://" ]];
then echo "absolute.";
fi;
You need to use regex without quote:
url="http://test"
if [[ "$url" =~ ^http:// ]]; then
echo "absolute."
fi
This outputs `absolute. as regex needs to be without quote in newer BASH (after BASH v3.1)
Or avoid regex and use glob matching:
if [[ "$url" == "http://"* ]]; then
echo "absolute."
fi