Usando el comando `select` para imprimir un menú en Bash


10

Estoy tratando de implementar un menú simple usando el selectcomando. El script (para fines de prueba) es el siguiente:

#!/bin/bash
echo "*******************"
PS3='Select an option and press Enter: '
options=("apache" "named" "sendmail")
select opt in "${options[@]}"
do
  case $opt in
        "apache")
          date
          ;;
        "named")
          echo "test"
          ;;
        "sendmail")
          echo "test 2"
          ;;
        *) echo "invalid option";;
  esac
done
echo "*********************"

El script no reconoce ninguna entrada válida que doy y siempre imprime el mensaje de "opción no válida". ¿Qué estoy haciendo mal en este script?


44
Su entrada es 1, 2 o 3, ¿verdad?
enzotib

Respuestas:


11

Su menú que se muestra en select se verá así:

1) apache
2) named
3) sendmail
Select an option and press Enter: 

En este momento, ingresa "1" o "2" o "3": no escribe la palabra.

Además, se selectrepetirá hasta que vea un breakcomando, por lo que desea esto:

  case $opt in
        "apache")
          date
          break
          ;;
        "named")
          echo "test"
          break
          ;;
        "sendmail")
          echo "test 2"
          break
          ;;
        *) echo "invalid option";;
  esac

Si desea permitir que el usuario ingrese el número o la palabra, puede escribir esto:

select opt in "${options[@]}"; do
  case "$opt,$REPLY" in
    apache,*|*,apache)     do_something; break ;;
    named,*|*,named)       do_something; break ;;
    sendmail,*|*,sendmail) do_something; break ;;
  esac
done

La coma no tiene significado sintáctico, solo está ahí para poder coincidir con el patrón en la variable $ REPLY (que es lo que el usuario realmente escribió) o la variable $ opt


El selectcomando necesita un break, no case.
Glenn Jackman

¡Gracias! No me di cuenta de que se trataba de opciones numéricas. Duhh!
Sumod

Ja, yo también programo en C y, sí necesitas un breakallí en cada sección. Sin embargo, nunca se necesitará una breaken un caso ... esac bloque en un script de shell . Puede suceder tan fácilmente confundirlos. :-)
syntaxerror

1
@syntaxerror, tienes razón, no es necesario breakpara case. Sin embargo, necesita un breakpara escapar del selectbucle.
Glenn Jackman

@glenn jackman Me gustaría que esto se convierta en un comentario más útil (ver a continuación). Por lo tanto, sería genial si aceptaras eliminar tu comentario de las 12:55. Haré lo mismo con el mío, por supuesto.
syntaxerror

3

Su $optvariable se establecerá en la palabra de opción correspondiente al número que ingrese el usuario. Si desea ver lo que el usuario realmente escribió, mire $REPLY.


1
Dado que se casecompara $optcon "apache", "named" y "sendmail", es correcto y no hay que cambiar nada.
manatwork

@manatwork, a menos que el OP quiera que el usuario escriba las palabras "apache", "named" o "sendmail" en lugar de presionar 1, 2 o 3.
Kusalananda

Interesante. $ REPLY retiene 1/ 2/ 3, y $ opt retiene apache/ named/sendmail
Peter.O

@fred, sí, $REPLYes lo que escribió el usuario, y si era un número válido, $optserá la palabra correspondiente a ese número.
Kusalananda
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.