Solución:
Solución 1:
Creo que deberías echarle un vistazo al diálogo o al látigo.
Editar:
Aquí hay un script de ejemplo que usa las opciones de su pregunta:
#!/bin/bash
cmd=(dialog --separate-output --checklist "Select options:" 22 76 16)
options=(1 "Option 1" off # any option can be set to default to "on"
2 "Option 2" off
3 "Option 3" off
4 "Option 4" off)
choices=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty)
clear
for choice in $choices
do
case $choice in
1)
echo "First Option"
;;
2)
echo "Second Option"
;;
3)
echo "Third Option"
;;
4)
echo "Fourth Option"
;;
esac
done
Solucion 2:
Si usted piensa whiptail
es complejo, aquí va un código de solo bash que no exactamente Lo que quieras. Es corto (~ 20 líneas), pero un poco críptico para un principiante. Además de mostrar “+” para las opciones marcadas, también proporciona comentarios para cada acción del usuario (“opción no válida”, “opción X marcada” / desmarcada, etc.).
Dicho esto, ¡ahí lo tienes!
Espero que lo disfrutes … fue un desafío bastante divertido hacerlo 🙂
#!/bin/bash
# customize with your own.
options=("AAA" "BBB" "CCC" "DDD")
menu() {
echo "Avaliable options:"
for i in ${!options[@]}; do
printf "%3d%s) %sn" $((i+1)) "${choices[i]:- }" "${options[i]}"
done
if [[ "$msg" ]]; then echo "$msg"; fi
}
prompt="Check an option (again to uncheck, ENTER when done): "
while menu && read -rp "$prompt" num && [[ "$num" ]]; do
[[ "$num" != *[![:digit:]]* ]] &&
(( num > 0 && num <= ${#options[@]} )) ||
{ msg="Invalid option: $num"; continue; }
((num--)); msg="${options[num]} was ${choices[num]:+un}checked"
[[ "${choices[num]}" ]] && choices[num]="" || choices[num]="+"
done
printf "You selected"; msg=" nothing"
for i in ${!options[@]}; do
[[ "${choices[i]}" ]] && { printf " %s" "${options[i]}"; msg=""; }
done
echo "$msg"
Solución 3:
Esta es una forma de hacer exactamente lo que desea utilizando solo funciones de Bash sin dependencias externas. Marca las selecciones actuales y le permite alternarlas.
#!/bin/bash
# Purpose: Demonstrate usage of select and case with toggleable flags to indicate choices
# 2013-05-10 - Dennis Williamson
choice () {
local choice=$1
if [[ ${opts[choice]} ]] # toggle
then
opts[choice]=
else
opts[choice]=+
fi
}
PS3='Please enter your choice: '
while :
do
clear
options=("Option 1 ${opts[1]}" "Option 2 ${opts[2]}" "Option 3 ${opts[3]}" "Done")
select opt in "${options[@]}"
do
case $opt in
"Option 1 ${opts[1]}")
choice 1
break
;;
"Option 2 ${opts[2]}")
choice 2
break
;;
"Option 3 ${opts[3]}")
choice 3
break
;;
"Option 4 ${opts[4]}")
choice 4
break
;;
"Done")
break 2
;;
*) printf '%sn' 'invalid option';;
esac
done
done
printf '%sn' 'Options chosen:'
for opt in "${!opts[@]}"
do
if [[ ${opts[opt]} ]]
then
printf '%sn' "Option $opt"
fi
done
Para ksh, cambie las dos primeras líneas de la función:
function choice {
typeset choice=$1
y el tinglado a #!/bin/ksh
.
Solución 4:
Escribí una biblioteca llamada cuestionario, que es un mini-DSL para crear cuestionarios de línea de comandos. Solicita al usuario que responda una serie de preguntas e imprime las respuestas en stdout.
Hace que su tarea sea realmente fácil. Instalarlo con pip install questionnaire
y crea un guión, p. ej. questions.py
, como esto:
from questionnaire import Questionnaire
q = Questionnaire(out_type="plain")
q.add_question('options', prompt="Choose some options", prompter="multiple",
options=['Option 1', 'Option 2', 'Option 3', 'Option 4'], all=None)
q.run()
Entonces corre python questions.py
. Cuando haya terminado de responder a las preguntas, se imprimirán en formato estándar. Funciona con Python 2 y 3, uno de los cuales es casi seguro que esté instalado en su sistema.
También puede manejar cuestionarios mucho más complicados, en caso de que alguien quiera hacer esto. A continuación se muestran algunas características:
- Imprime las respuestas como JSON (o como texto sin formato) en stdout
- Permite a los usuarios retroceder y volver a responder preguntas.
- Admite preguntas condicionales (las preguntas pueden depender de respuestas anteriores)
- Admite los siguientes tipos de preguntas: entrada sin procesar, elija una, elija muchas
- Sin acoplamiento obligatorio entre la presentación de preguntas y los valores de respuesta
Solución 5:
Aquí hay una función bash que permite al usuario seleccionar múltiples opciones con las teclas de flecha y la barra espaciadora, y confirmar con Enter. Tiene una agradable sensación de menú. Lo escribí con la ayuda de https://unix.stackexchange.com/a/415155. Se puede llamar así:
multiselect result "Option 1;Option 2;Option 3" "true;;true"
El resultado se almacena como una matriz en una variable con el nombre proporcionado como primer argumento. El último argumento es opcional y se utiliza para seleccionar algunas opciones de forma predeterminada. Se parece a esto.
function prompt_for_multiselect {
# little helpers for terminal print control and key input
ESC=$( printf " 33")
cursor_blink_on() { printf "$ESC[?25h"; }
cursor_blink_off() { printf "$ESC[?25l"; }
cursor_to() { printf "$ESC[$1;${2:-1}H"; }
print_inactive() { printf "$2 $1 "; }
print_active() { printf "$2 $ESC[7m $1 $ESC[27m"; }
get_cursor_row() { IFS=';' read -sdR -p $'E[6n' ROW COL; echo ${ROW#*[}; }
key_input() {
local key
IFS= read -rsn1 key 2>/dev/null >&2
if [[ $key = "" ]]; then echo enter; fi;
if [[ $key = $'x20' ]]; then echo space; fi;
if [[ $key = $'x1b' ]]; then
read -rsn2 key
if [[ $key = [A ]]; then echo up; fi;
if [[ $key = [B ]]; then echo down; fi;
fi
}
toggle_option() {
local arr_name=$1
eval "local arr=("${${arr_name}[@]}")"
local option=$2
if [[ ${arr[option]} == true ]]; then
arr[option]=
else
arr[option]=true
fi
eval $arr_name="("${arr[@]}")"
}
local retval=$1
local options
local defaults
IFS=';' read -r -a options <<< "$2"
if [[ -z $3 ]]; then
defaults=()
else
IFS=';' read -r -a defaults <<< "$3"
fi
local selected=()
for ((i=0; i<${#options[@]}; i++)); do
selected+=("${defaults[i]}")
printf "n"
done
# determine current screen position for overwriting the options
local lastrow=`get_cursor_row`
local startrow=$(($lastrow - ${#options[@]}))
# ensure cursor and input echoing back on upon a ctrl+c during read -s
trap "cursor_blink_on; stty echo; printf 'n'; exit" 2
cursor_blink_off
local active=0
while true; do
# print options by overwriting the last lines
local idx=0
for option in "${options[@]}"; do
local prefix="[ ]"
if [[ ${selected[idx]} == true ]]; then
prefix="[x]"
fi
cursor_to $(($startrow + $idx))
if [ $idx -eq $active ]; then
print_active "$option" "$prefix"
else
print_inactive "$option" "$prefix"
fi
((idx++))
done
# user key control
case `key_input` in
space) toggle_option selected $active;;
enter) break;;
up) ((active--));
if [ $active -lt 0 ]; then active=$((${#options[@]} - 1)); fi;;
down) ((active++));
if [ $active -ge ${#options[@]} ]; then active=0; fi;;
esac
done
# cursor position back to normal
cursor_to $lastrow
printf "n"
cursor_blink_on
eval $retval="("${selected[@]}")"
}