muradin
muradin

Reputation: 1277

use of special characters in if statement in bash

I'm unfamiliar with bash scripting. I wrote a script check arguments. the code is:

for (( i=1; i<=4; i++ ))
do
        if ! [[ "$"$i =~ .*[^0-9].* ]]; then
                echo "bad input was $i"
        fi
done

Actually i want to split non numerical arguments, But it seems that "$"$i is wrong because the answer is always true or false independent of arguments. can anybody tell me what is the mistake?

Upvotes: 2

Views: 3917

Answers (3)

Idriss Neumann
Idriss Neumann

Reputation: 3838

Use something like this :

for i in "$@"; do
     [[ $i =~ .*[^0-9].* ]] || echo "bad input was $i"
done

N.B : It's not necessary to use doubles quotes arround the variable with the [[ internal instruction.

Upvotes: 1

anubhava
anubhava

Reputation: 785491

If condition should be like this:

if [[ ! "$i" =~ [^0-9] ]]; then

OR remove 2 negatives:

if [[ "$i" =~ [0-9] ]]; then

OR use glob:

if [[ "$i" == *[0-9]* ]]; then

Which means $i contains a digit 0-9

Update: Based on your comments it looks like you are looking for BASH variable indirection like this script check-num.sh:

#!/bin/bash
for (( i=1; i<=$#; i++ )); do
    [[ "${!i}" != *[0-9]* ]] && echo "bad input was ${!i}"
done

You can run this script as: ./check-num.sh 1 2 x 4 a

Note how ${!i} syntax is being used here to access the variable's $1, $2, $3 etc that is called BASH variable indirection. You shouldn't use $$i for this purpose.

As per BASH manual:

If the first character of parameter is an exclamation point, a level of variable indirection is introduced. Bash uses the value of the variable formed from the rest of parameter as the name of the variable; this variable is then expanded and that value is used in the rest of the substitution, rather than the value of parameter itself.

Upvotes: 1

chepner
chepner

Reputation: 531758

You seem to be trying to use indirect parameter expansion.

for (( i=1; i<=4; i++ ))
do
    if ! [[ ${!i} =~ .*[^0-9].* ]]; then
        echo "bad input was $i"
    fi
done

However, it's cleaner to just iterate over the parameters directly, rather than over their position:

for arg in "${@:1:4}"; do
    if ! [[ $arg =~ .*[^0-9].* ]]; then
        echo "bad input was $arg"
    fi
done

Upvotes: 3

Related Questions