2

d is an internal server lookup tool I use.

I am looking to allow a user to input any number between 0 (or 1) and 9999 (let's call this userinput) and have it display the result of:

d $userinput (e.g. 1234)

Then manipulate the results of that lookup (below gets rid of everything but the IP address to ping later):

 grep -E -o '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)'`

I know I need to use the while true; do read $blah etc etc. I am just not familiar with read enough to format it properly and more importantly:

get it to prompt for a numerical input between 0-9999

4 Answers 4

5

The other answers have many flaws, because they check that the user didn't input a number outside of the range they want. But what if a user enters something that is not a number? their strategy is broken from the start.

Instead it's better to let go only when we're sure that the user entered a number which lies within the wanted range.

while :; do
    read -ep 'Enter server number: ' number
    [[ $number =~ ^[[:digit:]]+$ ]] || continue
    (( ( (number=(10#$number)) <= 9999 ) && number >= 0 )) || continue
    # Here I'm sure that number is a valid number in the range 0..9999
    # So let's break the infinite loop!
    break
done

The regex [[ $number =~ ^[[:digit:]]+$ ]] makes sure that the user only entered digits.

The clumsy (number=(10#$number)) part is here so that if the user enters a number that starts with a 0, bash would try to interpret it in radix 8 and we'd get a wrong result (e.g., if the user enters 010) and even an error in the case when a user enters, e.g., 09 (try it without this guard).


If you only want to prompt once and exit when the user inputs invalid terms, you have the logic:

read -ep 'Enter server number: ' number
[[ $number =~ ^[[:digit:]]+$ ]] || exit 1
(( ( (number=(10#$number)) <= 9999 ) && number >= 0 )) || exit 1
# Here I'm sure that number is a valid number in the range 0..9999

If you want to explain to the user why the script exited, you can use a die function as:

die() {
    (($#)) && printf >&2 '%s\n' "$@"
    exit 1
}
read -ep 'Enter server number: ' number
[[ $number =~ ^[[:digit:]]+$ ]] ||
    die '*** Error: you should have entered a number'
(( ( (number=(10#$number)) <= 9999 ) && number >= 0 )) ||
    die '*** Error, number not in range 0..9999'
# Here I'm sure that number is a valid number in the range 0..9999
Sign up to request clarification or add additional context in comments.

Comments

2

<--edit-->

if all you want is the mechanic for prompting, try this:

echo -n "Enter server number:"
read userinput

then run validation checks on the input like this:

if [[ $userinput -lt 0 || $userinput -gt 9999 ]]   # checks that the input is within the desired range
 then
  echo "Input outside acceptable range."
else
  # insert your grep and ping stuff here
fi

<--end edit-->

on first read, i thought your problem sounded ideal for a wrapper script, so i was going to suggest this:

$ cat wrapper.sh
#!/usr/bin/bash

userinput=$1

if [[ $# != 1 ]]   # checks that number of inputs is exactly one
 then
  echo "Too many inputs."
  exit 2
elif [[ $userinput -lt 0 || $userinput -gt 9999 ]]   # checks that the input is within the desired range
 then
  echo "Input outside acceptable range."
  exit 3
fi

output=`d "$userinput"`

ping_address=`grep -E -o '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)' <("$output")`

ping "$ping_address"

then call the script with like this:

$ wrapper.sh 1243

1 Comment

Perfect edit, thank you so much :) after else I just do d $userinput | grep... and it works a charm.
2

If you just want a number between two values, you can test their values:

 read x
 while [[ $x -lt 0 || $x -gt 9999 ]]; do
    echo "bad value for x"
    read x
 done
 echo "x=$x"

Comments

0

The read command doesn't prompt itself. Use a normal echo before to actually display a prompt. Use echo -n to not add a newline.

4 Comments

Searching around for "bash prompt for input" just comes back with example of using read like so: read -p "Enter value" variable case "variable" in...how do I prompt via echo or reference read from echo. e.g. stackoverflow.com/questions/1885525/…
@Zippyduda The -p option is an extension that doesn't exist in the standard.
Hm, fair enough. Why is it used in that link I posted?
@Zippyduda Ah, I found it now in the Bash manual. It's a Bash-specific extension. Have you tried it?

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.