0

I am trying to write a script which connects to a database then run a query that returns count of rows in a table. sometimes database or table have problems and instead of an integer they return an error. for example:
A database connection does not exist
i want to determine if output is the integer i want or its an error. i searched through various posts but none of them worked in my script. what should i do?

DB2PATH=/bin/db2
$DB2PATH connect to $1 >> /dev/null
count=$($DB2PATH -x " select count(*) from TEST122 ")


if ! [[ "$count" =~ ^[0-9]+$ ]]
then
    echo "string"
else
    echo $count
fi

i changed the if condition in many different ways. i used -eq and -ne. it keep returning string. and the value of count is 11.

update:
printf '%s' "$count" | hexdump -c output:

0000000                                       1   1
000000b
4
  • 1
    If count is actually 11, the if works fine for me. Maybe the command output has spaces in it, or quotes, or some other weird characters.
    – muru
    Oct 31, 2018 at 8:19
  • 3
    @BlackCrystal: Can you do printf '%s' "$count" | hexdump -c and paste above?
    – Inian
    Oct 31, 2018 at 8:20
  • @Inian what does that command do? i edited my post Oct 31, 2018 at 8:26
  • 2
    @BlackCrystal: As muru has indicated in his comment, the variable has some extra spaces present, that's why you see it is matching the string type
    – Inian
    Oct 31, 2018 at 8:27

3 Answers 3

3

To ignore and trim leading and trailing whitespace around the number:

if [[ $count =~ ^[[:space:]]*([[:digit:]]+)[[:space:]]*$ ]]; then
  echo number
  count=${BASH_REMATCH[1]}
else
  echo other
fi

Or with standard sh syntax:

trimmed=${count#"${count%%[![:space:]]*}"}
trimmed=${trimmed%"${count##*[![:space:]]}"}
case $trimmed in
  ("" | *[![:digit:]]*) echo other;;
  (*) echo number; count=$trimmed;;
esac
2

Looks like the variable count has some extra undesirable spaces which is causing your condition to fail it to be an integer type.

You need to strip out the extra spaces in your variable to fix it. Use an external tool like xargs to remove the spaces. The useful thing with xargs is it swallows up both leading and trailing spaces in the variable.

if ! [[ $( xargs <<< "$count" ) =~ ^[0-9]+$ ]]
then
    echo "string"
else
    echo $count
fi

If not for an external tool like xargs use the parameter expansion provided by the shell itself

if ! [[ "${count// /}" =~ ^[0-9]+$ ]]
then
    echo "string"
else
    echo $count
fi

The syntax ${count// /} will replace all the spaces with an empty string and the resultant string is used in the comparison with the regular expression defined.

5
  • 1
    You could also use the arithmetic context: (( count = count )) will succeed and convert count to a number if it didn't have invalid characters (leading, trailing spaces are fine). It will fail with invalid characters, so you could do if (( count = count )); then echo "$count"; else echo string; fi
    – muru
    Oct 31, 2018 at 8:38
  • 2
    @muru, that's both wrong and dangerous, (( count = count )) returns true if $count contains an artihmetic expression that resolves to a non-0 number. So it returns false for 0 even though that's a valid decimal number, and true for RANDOM (most likely), 1 + a[$(reboot)0] (which also reboots), PATH=123... Oct 31, 2018 at 9:16
  • 1
    Note that your first one would think that '1'\2"3" or -n 123 (with some echo implementations) is a valid number. The second one would think that 1 2 34 is a valid number. Oct 31, 2018 at 9:23
  • @StéphaneChazelas woah. Thanks for the correction!
    – muru
    Oct 31, 2018 at 9:30
  • 2
0

Putting negation inside expresion gives me correct results:

if [[ ! "$count" =~ ^[0-9]+$ ]]
then
    echo "string"
else
    echo $count
fi

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .