2

I've been killing myself over this trying to figure it out, and I know it's probably super simple, so hoping a new pair of eyes can help. I have a Bourne shell (sh) script that I'm writing and it takes a list of integers as the input (and amount from 1 integer up, ideally I'd like to take both positive and negative ints). I'm trying to do an error check for the case if someone inputs something other than an integer. They could input "1 2 3 4 5 a" and it'd give an error, because the a is not an int.

I have an error check for no inputs that works, and I have code that does stuff to the list of integers themselves, but even when strings are given it still gets to my final code block.

I currently have a for loop to iterate through each item in the list of integers, then an if loop to give the error message if the argument in question isn't an int. I've tried a few different versions of this, but this is the most recent one so I've put it below.

for i in $@; do 
    if [ $i -ge 0 ] 2>/dev/null; then
        echo "Invalid input: integers only."
        exit 1
    fi 
done

3 Answers 3

2
#!/bin/sh
#

for i in "$@"
do 
    case "${i#[-+]}" in 
        0) 
            echo cannot be 0?
            exit 1
            ;; 
        *[!0-9]* | '')
            echo not int
            exit 2
            ;; 
    esac
done

echo i\'m ok

This should work, for both positive and negative ints. And if you admit that 0 is an integer, just delete the first case.

Almost duplicate: BASH: Test whether string is valid as an integer? And here is a good answer for posix. https://stackoverflow.com/a/18620446/7714132

Sign up to request clarification or add additional context in comments.

2 Comments

YES! This is the first one that's worked! Thank you! Also, would you mind explaining the logic because it so I fully understand how it's implemented?
It's pretty obvisous, you should dive in bash a little. Issue 'man bash' and search 'case', 'Pathname Expansion', 'Remove matching prefix pattern' and so on.
1

You could use a regex:

my_script.sh

for i in $@ ; do 
    if ! [[ "$i" =~ ^-?[0-9]+$ ]] ; then
        echo "Invalid input: integers only."
        exit 1
    fi
done

Example:

$ sh my_script.sh 1 2 3 4
$ sh my_script.sh 1 2 -12
$ sh my_script.sh 1 2 -12-2
Invalid input: integers only.
$ sh my_script.sh 1 2 a b
Invalid input: integers only.

Explanation of the regex:

  • ^: beginning of the string
  • -?: 0 or 1 times the character -
  • [0-9]+: 1 or more digit
  • $: end of the string

3 Comments

What is the difference between using one "[ ]" vs two "[[ ]]"? I've read that the two are for bash, but if this is in a bourne shell, would it work?
I also tried it both ways (single and double brackets) and it's still not working :/
This works in bash/ksh/zsh, but not in ash/dash/bourne/posix
0

In POSIX sh, you can match your string against a glob with case:

#!/bin/sh
for i
do
  case "$i" in
    *[!0-9]*)
      echo "Integers only" >&2
      exit 1
  esac
done
echo "Ok"

Here's how it runs:

$ ./myscript 1 2 3 4 5
Ok

$ ./myscript 1 2 3 4 5 a
Integers only

The problem with your approach is primarily that you're checking for success rather than failure: [ will fail when the input is invalid.

4 Comments

What is the purpose of the single round bracket in this?
@MandyLB Can you be more specific? For example, "I wrote a script mytest containing the line ./myscript 1 2 3 , but when I run ./mytest I still get "Integers only" when I expected "Ok""
I have a full script, and like I said in my initial post, it works for checking for 0 inputs, and works for all integers, but the error check for non-integers doesn't work. The offered suggestions for how to fix the code (in my initial post) hasn't worked, and it still goes to the next code block and runs the inputs like integers, even when the check is supposed to stop that. Never gives an error saying the input isn't an int.
@MandyLB I don't understand. Do you get different results when you repeat my test cases? Or are you saying that the test cases worked fine, but you weren't able to apply it to a larger script?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.