gino gino
gino gino

Reputation: 269

Regular expression Bash issue

I have to match a string composed of only lowercase characters repeated 2 times , for example ballball or printprint. For example the word ball is not accepted because is not repeated 2 time. For this reason I have this code:

read input
expr='^(([a-z]*){2})$'

if [[ $input =~ $expr ]]; then

echo "OK string"
      exit 0

fi

exit 10

but it doesn't work , for example if I insert ball the script prints "OK string". What do I wrong?

Upvotes: 1

Views: 79

Answers (3)

Benjamin W.
Benjamin W.

Reputation: 52506

Not all Bash versions support backreferences in regexes natively. If yours doesn't, you can use an external tool such as grep:

read input
re='^\([a-z]\+\)\1$'

if grep -q "$re" <<< "$input"; then
    echo "OK string"
    exit 0
fi

exit 1

grep -q is silent and has a successful exit status if there was a match. Notice how (, + and ) have to be escaped for grep. (grep -E would understand () without escaping.)

Also, I've replaced your * with + so we don't match the empty string.

Alternatively: your requirement means that a matching string has two identical halves, so we can check for just that, without any regexes:

read input
half=$(( ${#input} / 2 ))
if (( half > 0 )) && [[ ${input:0:$half} = ${input:$half} ]]; then
    echo "OK string"
fi

This uses Substring Expansion; the first check is to make sure that the empty string doesn't match.

Upvotes: 2

Henk Langeveld
Henk Langeveld

Reputation: 8456

The regex [a-z]* will match any alphanumeric or empty string. ([a-z]*){2} will match any two of those. Ergo, ^(([a-z]*){2})$ will match any string containing zero or more alphanumeric characters.

Using the suggestion from @hwnd (replacing {2} with \1) will enforce a match on two identical strings.

N.B: You will need a fairly recent version of bash. Tested in bash 4.3.11.

Upvotes: -1

mauro
mauro

Reputation: 5950

Your requirement is to match strings made of two repeated words. This is easy to do by just checking if the first half of your string is equal to the remaining part. No need to use regexps...

$ var="byebye" && len=$((${#var}/2))
$ test ${var:0:$len} = ${var:$len} && { echo ok ; } || echo no  
ok
$ var="abcdef" && len=$((${#var}/2))
$ test ${var:0:$len} = ${var:$len} && { echo ok ; } || echo no  
no

Upvotes: 0

Related Questions