Simple Bash and RegEx Questions [duplicate]
Asked Answered
A

4

8

I'm unable to get a pattern to match properly using regex in bash 4.1. I've read some information on about differences in quotes vs not quotes but I don't think that is my problem.

My goal is to check and make sure that the script is provided a valid ID. A valid ID in this case is a string of 9 digits. It's my understand that a regex expression for that is \d{9}. Given that here is my code snippet to check:

id=$1       
if [[ $id =~ \d{9} ]]; then
     echo "This is a vaild ID"
else
     echo "This is not a vaild ID"
fi

Then call the script with:

 ./script 987654321

Something obvious that I am missing?

Ashantiashbaugh answered 15/9, 2011 at 23:21 Comment(3)
You should edit your question to include why you think it isn't working. are you getting to the else statment? or are you getting a syntax error. Good luck.Rueful
Regexp in Bash (v3 and later) doesn't support \d, you can use [0-9] or the [:digit:] posix character class.Phillie
The fully portable way would be to use a glob pattern, i.e. case $id in [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]) echo fine ;; *) die in anguish;; esacTremolant
H
9

This will work: if [[ $id =~ [[:digit:]]{9} ]] – David W. 11 hours ago


@David I tried that on bash and it didn't seem to work. – Vivin Paliath 10 hours ago


I've just written a test program:

#! /bin/bash

for id in 123456789 12345689 1234567890 987654321
do
    if [[ $id =~ ^[[:digit:]]{9}$ ]]
    then
        echo "$id is 9 digits long"
    else
        echo "$id is bad"
    fi
done

And I got the following output:

DaveBook:~ david$ ./test.sh
123456789 is 9 digits long
12345689 is bad
1234567890 is bad
987654321 is 9 digits long
DaveBook:~ david$ 

I'm using BASH 3.2.48 for Mac OS X and Bash 4.1.10(4) for Cygwin (Wow, the Mac version is that old?). I haven't tested this on a Linux box.

What version are you using? Are you doubling the square braces around :digit:? It has to be [[:digit:]] and not [:digit:].

I also realized I need the ^ and $ anchors in there because you don't want to match foo123456789bar or 1234567890123456790. Was this an issue you had?

The thing is that [[:digit:]] should have worked. I've used it in many Bash shell scripts thinking it was fairly universal. However, if you have a BASH shell where it doesn't work, I'm going to have to stop using it.

Heliotropism answered 16/9, 2011 at 13:49 Comment(4)
I don't know what I was smoking earlier, but I just tried it out now and it works. I could have sworn that it didn't work when I tried it the last time because it was one of the first things I tried.Circumlocution
This is what I was looking for thank you. Do you have a reference article for finding equvalancies between items such as /d & [[:digit:]] Or are the man pages the best resource?Ashantiashbaugh
Actually, the best source is the Perl documentation. After all, all of the extended regular expression stuff originally came from Perl. Take a look at perldoc perlre and the part about the character classes.Heliotropism
great thanks ! how would you specify a number up to 9 digits though?Pageboy
M
9

As others already answered you should use [0-9]{9} because \d is not supported. But another important part is, you have to use anchors!

^[0-9]{9}$

The ^ anchors the regex to the start of the string and the $ anchors it to the end. If you don't use them your regex will match on every string that contains 9 digits in a sequence, like "abc123456789", "asdf123456789zui" or "123456789FOOBAR".

Molest answered 16/9, 2011 at 5:49 Comment(1)
Why do you have to put [[ and ]] around :digit:?Miscall
H
9

This will work: if [[ $id =~ [[:digit:]]{9} ]] – David W. 11 hours ago


@David I tried that on bash and it didn't seem to work. – Vivin Paliath 10 hours ago


I've just written a test program:

#! /bin/bash

for id in 123456789 12345689 1234567890 987654321
do
    if [[ $id =~ ^[[:digit:]]{9}$ ]]
    then
        echo "$id is 9 digits long"
    else
        echo "$id is bad"
    fi
done

And I got the following output:

DaveBook:~ david$ ./test.sh
123456789 is 9 digits long
12345689 is bad
1234567890 is bad
987654321 is 9 digits long
DaveBook:~ david$ 

I'm using BASH 3.2.48 for Mac OS X and Bash 4.1.10(4) for Cygwin (Wow, the Mac version is that old?). I haven't tested this on a Linux box.

What version are you using? Are you doubling the square braces around :digit:? It has to be [[:digit:]] and not [:digit:].

I also realized I need the ^ and $ anchors in there because you don't want to match foo123456789bar or 1234567890123456790. Was this an issue you had?

The thing is that [[:digit:]] should have worked. I've used it in many Bash shell scripts thinking it was fairly universal. However, if you have a BASH shell where it doesn't work, I'm going to have to stop using it.

Heliotropism answered 16/9, 2011 at 13:49 Comment(4)
I don't know what I was smoking earlier, but I just tried it out now and it works. I could have sworn that it didn't work when I tried it the last time because it was one of the first things I tried.Circumlocution
This is what I was looking for thank you. Do you have a reference article for finding equvalancies between items such as /d & [[:digit:]] Or are the man pages the best resource?Ashantiashbaugh
Actually, the best source is the Perl documentation. After all, all of the extended regular expression stuff originally came from Perl. Take a look at perldoc perlre and the part about the character classes.Heliotropism
great thanks ! how would you specify a number up to 9 digits though?Pageboy
C
3

Try this:

if [[ $id =~ [0-9]{9} ]]; then

It looks like bash doesn't recognize \d as [0-9].

Bash uses the Extended Regular Expression dialect, which doesn't support \d.

According to ERE's grammar (lexical conventions), escaped characters are of the form \SPEC_CHAR. SPEC_CHAR can be any one of the following:

^    .    [    $    (    )    |
*    +    ?    {    \
Circumlocution answered 15/9, 2011 at 23:32 Comment(1)
@David I tested it out and it works now. I have no idea why it didn't work the first time I tried it.Circumlocution
O
-2

The problem is \d gets turned into d before it's interpreted. Try double escaping.

\d{9} => d{9}
\\d{9} => \d{9}

Alternatively, you could put it in quotes

if [[ $id =~ "\d{9}" ]]
Outworn answered 15/9, 2011 at 23:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.