4

How do I check if a variable contains characters (regex) other than 0-9a-z and - in pure bash?

I need a conditional check. If the string contains characters other than the accepted characters above simply exit 1.

kenorb
  • 155,785
  • 88
  • 678
  • 743
Justin
  • 42,716
  • 77
  • 201
  • 296

3 Answers3

3

One way of doing it is using the grep command, like this:

 grep -qv "[^0-9a-z-]" <<< $STRING

Then you ask for the grep returned value with the following:

if [ ! $? -eq 0 ]; then
    echo "Wrong string"
    exit 1
fi

As @mpapis pointed out, you can simplify the above expression it to:

grep -qv "[^0-9a-z-]" <<< $STRING || exit 1

Also you can use the bash =~ operator, like this:

if [[ ! "$STRING" =~ [^0-9a-z-] ]] ; then  
    echo "Valid"; 
else 
    echo "Not valid"; 
fi
higuaro
  • 15,730
  • 4
  • 36
  • 43
  • 2
    you can also `grep ... || exit 1` – mpapis Nov 08 '13 at 02:35
  • Do I need to escape the `-` in `[^0-9a-z-]`, so `[^0-9a-z\-]`? Also, isn't the first case `echo "Not valid"` instead of `echo "Valid"`. – Justin Nov 08 '13 at 02:51
  • No, you don't need to escape the `-` (not even in the `grep` solution), the first case should be `Valid` because the conditional is negated (using the `!` operator before the regex test), the condition ask if `$STRING` contains a character that is **not** a digit, `-` or a letter, if this evaluates to `false` (`$STRING` contains only letters, digits and/or `-`) the negation turns the evaluation `true` – higuaro Nov 08 '13 at 03:33
  • Tangentially, see also [Why is testing “$?” to see if a command succeeded or not, an anti-pattern?](https://stackoverflow.com/questions/36313216/why-is-testing-to-see-if-a-command-succeeded-or-not-an-anti-pattern) – tripleee Oct 12 '22 at 05:49
2

case has support for matching:

case "$string" in
  (+(-[[:alnum:]-])) true ;;
  (*) exit 1 ;;
esac

the format is not pure regexp, but it works faster then separate process with grep - which is important if you would have multiple checks.

mpapis
  • 52,729
  • 14
  • 121
  • 158
  • `case` supports glob patterns, not regular expressions. The example uses extended glob patterns, which are often not enabled out of the box. But if your needs are simple, glob patterns are simpler to write and understand, and quite possibly faster to process than regular expressions. – tripleee Oct 12 '22 at 05:50
0

Using Bash's substitution engine to test if $foo contains $bar

bar='[^0-9a-z-]'
if [ -n "$foo" -a -z "${foo/*$bar*}" ] ; then
  echo exit 1
fi
Fritz
  • 1,293
  • 15
  • 27
NerdMachine
  • 155
  • 1
  • 3