Bash case Statement and Using Line Anchors?

Hello All,

I am writing a script that is to be placed on multiple servers, and of course I've started
running into some compatibility issues for certain shell commands.

The code below worked just fine on most of my machines except for a couple.
Here I had 4 separate lines in my script that checked the format of the user's input. Which
was set to "$new_command" --> i.e. new_command="$1" using the grep command...

    ### Patterns for checking the NEW Command...
     START_PATTERN="^command"
     ALIAS_PATTERN="^command\[[a-z0-9].*\]"
    EQUALS_PATTERN="^command\[[a-z0-9].*\]="
      PATH_PATTERN="^command\[[A-z0-9].*\]=/[A-z0-9]*/.*"

    ### Grep for new command beginning with the "command" keyword
    echo "$new_command" | grep -ioq "$START_PATTERN"
    GREPSTART_RETCODE=$?

    ### Grep for new command with "command[anyletters/numbers]"
    echo "$new_command" | grep -ioq "$ALIAS_PATTERN"
    GREPALIAS_RETCODE=$?

    ### Grep for new command with a "=" after the alias
    echo "$new_command" | grep -ioq "$EQUALS_PATTERN"
    GREPEQUALS_RETCODE=$?

    ### Grep for new command that has a Absolute Path after the "="
    echo "$new_command" | grep -ioq "$PATH_PATTERN"
    GREPPATH_RETCODE=$?

# ......
### HERE WAS A COUPLE IF STATEMENTS CHECKING ALL THE ABOVE'S RETURN CODES...
# ...... etc ......

Basically it did the grep on the same variable and checked for the specified pattern. Then
below those grep commands there was one if statement for each separate grep command's return code.
Basically they were all just "if [ $GREP***_RETURNCODE != 0 ]", then do some stuff.

But when I tested this on an AIX server in which I installed bash (which is bash version 3.2.16) I am
getting an error with the "grep" command's -o option... Must be an older version of grep (on ksh B.T.W.).

So I wanted to try something other then grep since it doesn't contain the -o option. I thought I would
use bash's "case" statement since it's much cleaner then using a bunch of if/elif/else statements. But
it doesn't seem to recognize the caret "^" symbol...? Is there a way to change this to where it would
recognize it?
Here's my case statement:

new_command="$1"


case "$new_command" in
       ^command)
            echo "Case 1 = TRUE"
        ;;
        ^command\[[a-z0-9].*\])
            echo "Case 2 = TRUE"
        ;;
        ^command\[[a-z0-9].*\]=)
            echo "Case 3 = TRUE"
        ;;
        ^command\[[A-z0-9].*\]=/[A-z0-9]*/.*)
            echo "Case 4 = TRUE"
        ;;
        *) 
            echo "IN Default Case, NONE ARE TRUE"
        ;;
esac

So is there any kind of shopt I can turn on to change this or does the case statement not have the ability to handle this?

Any thoughts would be great...

Thanks in Advance,
Matt

---------- Post updated at 04:43 PM ---------- Previous update was at 03:59 PM ----------

Hey All,

Yea, so I've been continually search around and I finally came across another forum where someone had a similar question to mine.
Not exactly about using line anchors but other symbols directly related to regex.

The response was that Bash's "case statement" does NOT use Regular Expressions, but uses Globs instead... I was afraid of that...

I guess I'll have to go with a set of if/elif/else statements...

Thanks Anyway,
Matt

You can match most with globs and put extra code within case 4 to trap non-digits between the '/' chars:

case "command[a_]=/9/rest" in
       command)
            echo "Case 1 = TRUE"
        ;;
        command\[[a-z0-9]*\])
            echo "Case 2 = TRUE"
        ;;
        command\[[a-z0-9]*\]=)
            echo "Case 3 = TRUE"
        ;;
        command\[[A-z0-9]*\]=/*/*)
            # check using grep for bad value inbetween / and /
            echo "Case 4 = TRUE"
        ;;
        *)
            echo "IN Default Case, NONE ARE TRUE"
        ;;
esac
1 Like

bash can work with regex too, though it's generally better to use case for portability.

#!/bin/bash
re_start='^command'
re_alias='^command\[[[:alnum:]][^]]*\]'
re_equals='^command\[[[:alnum:]][^]]*\]='
re_path='^command\[[[:alnum:]][^]]*\]=/[[:alnum:]]*/.*'


test=$1
if [[ $test =~ $re_path ]]; then
        echo "matches path regex [[${BASH_REMATCH[0]}]]"
elif [[ $test =~ $re_equals ]]; then
        echo "matches equals regex [[${BASH_REMATCH[0]}]"
elif [[ $test =~ $re_alias ]]; then
        echo "matches alias regex [[${BASH_REMATCH[0]}]"
elif [[ $test =~ $re_start ]]; then
        echo "matches start [[${BASH_REMATCH[0]}]"
else
        echo "bugger if i know"
fi

$ for str in 'command[new]=/path/to/stuff' 'command[abc123]=str' 'command[broke]noequals' 'command!=foobar'; do ./re "$str"; done
matches path regex [[command[new]=/path/to/stuff]]
matches equals regex [[command[abc123]=]
matches alias regex [[command[broke]]
matches start [[command]
1 Like

Hey Chubler_XL, thanks for the reply.

Yea, that's not a bad idea... Maybe I'll give that a try.

Hey neutronscott, thanks for the reply...

I originally did have this part of the script in If statements, but I was trying to shorten things up a bit and use a case
statement. But it looks like I'm going to go back to the if statements.

Thank you both for your help!

Thanks Again,
Matt