In Bash, can we match varying length of strings?
Eg.,
regex="FOO[0-9]{5}"
if [[ $1 =~ ${regex} ]]
will match FOO1111 or FOO98765 right...
But how do we match FOO1, FOO123 and FOO12345?
regex="FOO[0-9]{1-5}" doesnt work.
Is there a way do that in a simple manner or we just use:
regex5="FOO[0-9]{5}"
regex4="FOO[0-9]{4}"
regex3="FOO[0-9]{3}"
regex2="FOO[0-9]{2}"
regex="FOO[0-9]"
if [[ $1 =~ ${regex} || $1 =~ ${regex2} || $1 =~ ${regex3} || $1 =~ ${regex4} || $1 =~ ${regex5} ]]
You can use {min,max}:
regex="FOO[0-9]{1,5}"
And in fact you can use ^ and $ for exact match:
[[ $v =~ ^${regex}$ ]]
Test
$ v=FOO
$ [[ $v =~ ^${regex}$ ]] && echo "yes"
$
$ v=FOO1
$ [[ $v =~ ^${regex}$ ]] && echo "yes"
yes
$ v=FOO123456
$ [[ $v =~ ^${regex}$ ]] && echo "yes"
$
Related
For some reason, the following regular expression match doesn't seem to be working.
string="#Hello world";
[[ "$string" =~ 'ello' ]] && echo "matches";
[[ "$string" =~ 'el.o' ]] && echo "matches";
The first command succeeds (as expected), but the second one does not.
Shouldn't that period be treated by the regular expression as a single character?
Quoting the period causes it to be treated as a literal character, not a regular-expression metacharacter. Best practice if you want to quote the entire regular expression is to do so in a variable, where regular expression matching rules aren't in effect, then expand the parameter unquoted (which is safe to do inside [[ ... ]]).
regex='el.o'
[[ "$string" =~ $regex ]] && echo "matches"
string="#Hello world";
[[ "$string" =~ ello ]] && echo "matches";
[[ "$string" =~ el.o ]] && echo "matches";
Test
$ string="hh elxo fj"
$ [[ "$string" =~ el.o ]] && echo "matches";
matches
I have the following function
checkFormat()
{
local funcUserName=$1
if [[ "$funcUserName" != [a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9] ]];then
echo "1"
else
echo "0"
fi
}
if [[ $string != [a-zA-Z0-9]* ]]
Only returns true if the first character is not [a-zA-Z0-9]
if [[ $string != [a-zA-Z0-9]{5} ]]
Never returns true.
if [[ $string != [a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9] ]]
Returns as I want it to.
Why is this?
The code is to check that a username is 5 characters long and alphanumeric i.e.
Joe12 or 12345 but not %$134.
bash version 4.2.37
I suggest to replace
if [[ $string != [a-zA-Z0-9]{5} ]]
by
if [[ ! $string =~ ^[a-zA-Z0-9]{5}*$ ]]
to match a regex.
I cant really explain but check out the following:
name=$1
pat="\b[0-9a-zA-Z_]+\b"
if [[ $name =~ $pat ]]; then
echo "$name is ok as user name"
else
echo "$name is not ok as user name"
exit 1
fi
Test run:
./script test_user+
test_user+ is ok as user name
The username with a + sign should not match that regexp.
First of all:
\b is a PCRE extension; it isn't available in ERE, which the =~
operator in bash's [[ ]] syntax uses.
(From Bash regex match with word boundary)
Second, you don't want word boundaries (\b) if you wish to force the entire string to match. You want to match the start (^) and end ($):
pat="^[0-9a-zA-Z_]+\$"
if you dont want word bondry (guessed as you are trying username match) please use
^[0-9a-zA-Z_]+$
Contrary to the OP's experience and other answer it seems \b is supported on Ubuntu 14.04, bash 4.3.11 as word boundary. Here is a sample:
re='\bb[0-9]+\b'
[[ 'b123' =~ $re ]] && echo "matched" || echo "nope"
matched
[[ 'b123_' =~ $re ]] && echo "matched" || echo "nope"
nope
Even \< and \> also work fine as word boundaries:
re='\<b[0-9]+\>'
[[ 'b123' =~ $re ]] && echo "matched" || echo "nope"
matched
[[ 'b123_' =~ $re ]] && echo "matched" || echo "nope"
nope
However support of \b is specific to certain OS only. e.g. on OSX following works as word boundary:
[[ 'b123' =~ [[:\<:]]b[0-9]+[[:\>:]] ]] && echo "matched" || echo "nope"
matched
[[ 'b123_' =~ [[:\<:]]b[0-9]+[[:\>:]] ]] && echo "matched" || echo "nope"
nope
I can't get a string with spaces to validate. It works without spaces, but when I include a space in the string it fails. I have googled furiously but can't get it to work.
if [[ $string =~ ^"[A-Za-z ]"$ ]]; then
# true
else
# false
fi
I'm not sure what I'm missing here...
Use a variable to store your regex:
re='^[A-Za-z ]+$'
Then use it as:
[[ "string" =~ $re ]] && echo "matched" || echo "nope"
matched
[[ "string with spaces" =~ $re ]] && echo "matched" || echo "nope"
matched
If you want inline regex then use:
[[ "string with spaces" =~ ^[A-Za-z\ ]+$ ]] && echo "matched" || echo "nope"
matched
Or else use [[:blank:]] property:
[[ "string with spaces" =~ ^[A-Za-z[:blank:]]+$ ]] && echo "matched" || echo "nope"
matched
I should instead use following regex if its always space instead..
if [[ $string =~ ^"[A-Za-z ](\s)"$ ]]; then
# true
else
# false
fi
Cheers :)
the following code works fine on 3.5 bash but not in 4.1
regex='^WORD\-([^(WORD2)][^[:space:]]{1,}$)|(WORD2[[:space:]][^[:space:]]{2,}$)'
if ! [[ $appname =~ $regex ]]
then
printf "no match"
ct_dev_error=$((ct_dev_error+1))
fi
any soliutions? or ideas?
Your regex can be simplified to this:
regex='^WORD-(WORD2[[:space:]][^[:space:]]{2,}|[^[:space:]]+)$'
Test it:
appname='WORD-APP' && [[ $appname =~ $regex ]] && echo "${BASH_REMATCH[0]}"
WORD-APP
appname='WORD-BUD APP' && [[ $appname =~ $regex ]] && echo "${BASH_REMATCH[0]}"
appname='WORD-WORD2 APP' && [[ $appname =~ $regex ]] && echo "${BASH_REMATCH[0]}"
WORD-WORD2 APP
[^(WORD2)] is not actually negating match of WORD2. It is actually a negated character class and it is basically matching a single character that is NOT one of the characters in this list (WORD2).