0

If I pass a word as an argument by:

$./file.sh hello

it gives Even as output when it should print "Argument should be a number"

#!/bin/bash

set -e

if [[ -z $1 ]]
then
        echo "Argument expected"
else 
        if [[ $1 =~ "\D" ]] #This does not work as expected
        then
                echo "Argument should be a number"
        else
                a=$1%2
                if [[ a -eq 0 ]]
                then
                        echo "Even"
                elif [[ a -eq 1 ]]
                then
                        echo "Odd"
                fi  
        fi  
fi

#End of program

When I change "\D" to "[^0-9]" in the if statement, it works as expected and prints "Argument should be a number" to the console. Don't they both have the same meaning? If not, in what way are the two different from each other?

  • 1
    BTW, putting quotes on the right-hand side of `=~` tell the shell to treat that as a literal string and not a regex. (However, even if it *were* a regex it wouldn't be parsed as an instruction to match non-digits for the reason given). – Charles Duffy Feb 06 '18 at 22:55

3 Answers3

4

Bash uses POSIX Extended Regular Expressions, not PCRE. Instead of escape sequences like \D, it uses Bracket Expressions. The bracket expression for digits is

[:digit:]

and to match non-digits, you use this inside a character class with the negation operator:

[^[:digit:]]

As you can see, this is longer than just writing [^0-9], so it's not really a shorthand. It's useful for portability to other locales, since it will include their digits as well.

Barmar
  • 741,623
  • 53
  • 500
  • 612
1

Bash regex simply does not support PCRE regex syntax.

You might want to read up on different regex dialects and their history.

See e.g. Why are there so many different regular expression dialects?

tripleee
  • 175,061
  • 34
  • 275
  • 318
0

The POSIX equivalent of \D is [^[:digit:]].

chepner
  • 497,756
  • 71
  • 530
  • 681