How to prompt input from a user from a variable or bash array?
In a bash script, how would you script the following ?
USER_INPUT="1 2 3 4 5"
echo "Please select one of the following values: $USER_INPUT"
Prompt the user to choose a value in $USER_INPUT.
echo "command <user input> <iterate through remaining numbers not selected from $USER_INPUT>
For example, if the user selects “2”, the following commands are run.
command 2 1
command 2 3
command 2 4
command 2 5
Accept your input on the command line, not interactively. (Please!)
This is simple enough I would just use a shell function.
iter_the_command() {
max=5
[ "$#" -eq 1 ] && [ "$1" -ge 1 ] && [ "$1" -le "$max" ] ||
{ printf 'Error: please pass a number from 1 to %dn' "$max" >&2;
return 1;}
for i in $(seq "$max"); do
[ "$i" -eq "$1" ] && continue
somecommand "$1" "$i"
done
}
However, I have a strong suspicion this is an XY question and what you’re really trying to do would be more easily accomplished directly. (In other words, I find it hard to imagine a scenario where the above code would actually be useful and perform a needed function not better done otherwise.)
#!/bin/bash
values=( "Why is" "a raven" "like a" "writing desk?" )
select word in "${values[@]}"; do
if [[ -z "$word" ]]; then
printf '"%s" is not a valid choicen' "$REPLY" >&2
else
user_in="$(( REPLY - 1 ))"
break
fi
done
for (( i = 0; i < ${#values[@]}; ++i )); do
if (( i != user_in )); then
printf 'You did not pick "%s"n' "${values[$i]}"
fi
done
The select
command will present the user with a menu of choices. Upon picking a menu item, $REPLY
will be the number that the user entered, and $word
will be the value in the menu corresponding to that number. If an invalid choice is made, $word
will be empty.
The second part iterates over our array (which corresponds to your $USER_INPUT
string) using the C-like for
loop in bash
. If we come upon the index that the corresponds to the chosen value, we skip it. We print out all other values from our array.
You may obviously execute commands in the loop to:
for (( i = 0; i < ${#values[@]}; ++i )); do
if (( i != user_in )); then
printf 'command %s %sn' "$user_in" "${values[$i]}"
fi
done
or even
for (( i = 0; i < ${#values[@]}; ++i )); do
if (( i != user_in )); then
command "${values[$user_in]}" "${values[$i]}"
fi
done
which will try to run the actual things in $values
as a command.
Testing it (with the first version of the loop):
$ bash script.sh
1) Why is
2) a raven
3) like a
4) writing desk?
#? B
"B" is not a valid choice
#? 0
"0" is not a valid choice
#? 3
You did not pick "Why is"
You did not pick "a raven"
You did not pick "writing desk?"
If you can afford to modify $values
, and just want to output the things that the user didn’t pick, then the second part of the script (the loop) may be replaced with
unset values[$user_in]
printf 'You did not pick "%s"n' "${values[@]}"
#!/bin/bash
PROMPT=(1 2 3 4 5)
for i in ${PROMPT[*]}
do
printf " %dn" $i
done
echo "Choose an option: "
read var
unset PROMPT[$var-1]
PROMPT_new=(${PROMPT[@]})
for n in ${PROMPT_new[*]}
do
echo `command $var $n`
done