michaelmichael
michaelmichael

Reputation: 14125

Bash script that detects the type of argument it's given

I have a bash script that will take one argument: a product ID. The product ID can be in one of two formats: all numbers, or a mix of letters, numbers, and underscores. Depending on which type of ID is entered, the script will handle it in a slightly different way.

Right now, I'm using getopts with one flag for each subtype to distinguish between which type of product ID I'm going to be using in the script. For example:

./myscript -n 1034596

or

./myscript -v AB_ABCD_12345

With a simplified version of the script looking like this:

#!/bin/bash
while getopts ":n:v:" opt; do
  case $opt in
    n)
      echo "This is a numbers only ID." >&2
      ;;
    v)
      echo "This is a letters, numbers, underscore ID" >&2
      ;;
  esac
done

Since the formats are static, that is, the first type of ID will never be anything but numbers, is there any way to automatically distinguish between the two types of IDs and handle them appropriately without the need for the -n or -v flag? So, I could just enter ./myscript 1034596 and the script will know that since the argument contains nothing but numbers it should process it a specific way.

Upvotes: 1

Views: 6722

Answers (8)

Rod
Rod

Reputation: 55762

You could use grep to validate if the string passed in is a number:

#!/bin/bash
echo $1 | grep -q "^[0-9]*$"
if [ $? ]; then
    echo "Number"
else
    echo "Not a number"
fi

With comments updates:

#!/bin/bash

if grep -q "^[0-9]*$" <<< "$1"; then
    echo "Number"
else
    echo "Not a number"
fi

Upvotes: 1

There is a perhaps slightly more readable way with bash, but this can be done perfectly reasonably in pure portable sh.

unset LC_COLLATE
case $1 in
  *[!0-9A-Z_a-z]*) echo 1>&2 "Invalid product ID"; exit 2;;
  *[!0-9]*) echo "alphanumeric product ID";;
  *) echo "numeric product ID";;
esac

Upvotes: 2

Dennis Williamson
Dennis Williamson

Reputation: 360105

In Bash 3.2 or greater:

pattern1='^[0-9]+$'
pattern2='^[0-9a-zA-Z_]+$'
if [[ $1 =~ $pattern1 ]]
then
    echo "argument consists only of digits and is validated"
else
    echo "argument contains other characters"
    if [[ $1 =~ $pattern2 ]]
    then
        echo "argument is validated"
    else
        echo "argument contains invalid characters"
    fi
 fi

Upvotes: 1

SiegeX
SiegeX

Reputation: 140327

Pure Bash 3.X

#!/bin/bash
if [[ "$1" =~ ^[0-9]+$ ]]; then
  echo "This is a numbers only ID." >&2
else
  echo "This is a letters, numbers, underscore ID" >&2
fi

Output

$ ./argtype.sh 1034596
This is a numbers only ID.
$ ./argtype.sh AB_ABCD_12345
This is a letters, numbers, underscore ID

Upvotes: 4

Thedward
Thedward

Reputation: 1472

#!/bin/bash

shopt -s extglob

case "$1" in
  +([0-9]) ) echo "This is a numbers only ID." >&2
    ;;
  +([a-zA-Z0-9_]) ) echo "This is a letters, numbers, underscore ID" >&2
    ;;
  *) echo "Unrecognized Product ID" >&2
esac

Upvotes: 5

Brent Newey
Brent Newey

Reputation: 4509

Try this code:

#!/bin/bash
if [ $1 -eq $1 2> /dev/null ]; then
    echo number
else
    echo not number
fi

The output on your given input is:

brent@battlecruiser:~$ ./test2 1034596
number
brent@battlecruiser:~$ ./test2 AB_ABCD_12345
not number

Upvotes: 3

khachik
khachik

Reputation: 28693

#!/bin/sh

arg="$1"
output=`echo "$1" | grep -o "[0-9]\+"`
if [ "$output" == "$arg" ]; then
  echo "Numbers only"
else
  echo "Mixed"
fi

Upvotes: 1

GinoA
GinoA

Reputation: 732

Take a look at accepted the answer to this question. Around line 8 is a regex technique that you can adapt.

Upvotes: 1

Related Questions