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?

Sumod
fuente
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

Glenn Jackman
fuente
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.

Kusalananda
fuente
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