1

kindly have a look at the following code:

  echo "nhat and betah for each element 
        TIPS: 4 REAL NUMBER for each element(eg, 1.0 0.0 1.0 .1)"
  read -a nbh
  if [ ${#nbh[@]} -ne 4 ]
  then 
    echo "Wrong!! "
  fi

This error check (if loop) will terminate the program, if I forget to give exactly 4 elements. Is it possible, rather then terminating, give the user a chance again (and again)? i.e. basically go to the read -a nbh line again?

2 Answers 2

2

This should do:

#!/bin/bash
printf -v prompt '%s\n' "nhat and betah for each element" "TIPS: 4 REAL NUMBER for each element(eg, 1.0 0.0 1.0 .1)"
while read -p "$prompt" -a nbh; do
   ((${#nbh[@]}==4)) && break
   echo "Wrong!!"
done

(I've tried to render the script more acceptable regarding good practices).

Now you have a problem: how are you going to check that the user really inputs numbers? Let's pretend you have a function that can tell if a string is a valid representation of a number you accept. Let's call this function banana because it's a nice name. Then:

#!/bin/bash

banana() {
    # Like its name doesn't tell, this function
    # determines whether a string is a valid representation
    # of a number
    # ...
    # some wicked stuff here
    # ...
}

printf -v prompt '%s\n' "nhat and betah for each element" "TIPS: 4 REAL NUMBER for each element(eg, 1.0 0.0 1.0 .1)"
good=0
while ((!good)) && read -p "$prompt" -a nbh; do
    if ((${#nbh[@]}!=4)); then
        echo "Wrong!! you must give 4 numbers! (and I can count!)"
        continue
    fi
    for i in "${nbh[@]}"; do
        if ! banana "$i"; then
            echo "Your input \`$i' is not a valid number. It might be a valid banana, though. Check that with the local gorilla."
            continue 2
        fi
    done
    # If we're here, we passed all the tests. Yay!
    good=1
done

# At this point, you should check that we exited the loop because everything was
# valid, and not because `read` has an error (e.g., the user pressed Ctrl-D)
if ((!good)); then
    echo >&2 "There was an error reading your input. Maybe a banana jammed in the keyboard?"
    exit 1
fi

# Here you're safe: you have 4 entries that all are valid numbers. Yay.
echo "Bravo, you just won a banana!"

Now, for the function banana, you might want to use a regex (but then we'll have two problems, oh dear):

banana() {
    [[ $1 =~ ^-?([[:digit:]]*\.?[[:digit:]]+|[[:digit:]]+\.?[[:digit:]]*)$ ]]
}

Note that the scientific form is not supported here, so inputs like 1e-6 will not pass the test. If you need to also handle this, good luck, you're on your own!

You could also add an easter egg in your script: just after the while line, add:

[[ ${nbh[0],,} = gorilla ]] && { echo "banana"; continue; }
[[ ${nbh[0],,} = banana ]] && { echo "gorilla"; continue; }

Cheers!

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

Comments

1

A while "this condition is not matched" can make it:

#!/bin/bash

while [ ${#nbh[@]} -ne 4 ] <---- repeat until this is not true
do
  echo "nhat and betah for each element 
        TIPS: 4 REAL NUMBER for each element(eg, 1.0 0.0 1.0 .1)"
  read -a nbh
  if [ ${#nbh[@]} -ne 4 ]
  then 
    echo "Wrong!! "
  fi
done                       <---- finish while loop

Test

$ ./script
nhat and betah for each element 
        TIPS: 4 REAL NUMBER for each element(eg, 1.0 0.0 1.0 .1)
2 3
Wrong!! 
nhat and betah for each element 
        TIPS: 4 REAL NUMBER for each element(eg, 1.0 0.0 1.0 .1)
2 3 5 6
$

1 Comment

You doubled the code for the check (that [ ${#nbh[@]} -ne 4 ] here). If this is to change in future versions, the patch will likely be forgotten in one of both places. I think a while true would be better and then in the else branch have a break (not a Kitkat).

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.