Bash, advertencia sin argumentos y decisiones de casos


110

Estoy aprendiendo bash.

Me gustaría hacer un script simple que, cuando no se dan argumentos, muestra algún mensaje. Y cuando doy números como argumento, s dependiendo del valor, hace una cosa u otra.

También me gustaría conocer sugerencias de los mejores manuales en línea para principiantes en bash

Gracias

Respuestas:


176
if [[ $# -eq 0 ]] ; then
    echo 'some message'
    exit 0
fi

case "$1" in
    1) echo 'you gave 1' ;;
    *) echo 'you gave something else' ;;
esac

La Advanced Bash-Scripting Guide es bastante buena. A pesar de su nombre, trata lo básico.


RE: "salida 0". No sé si salir del guión era lo que tenía en mente. Pero sí, es una guía excelente.
— Trampas Kirk

Interpreté "y" como "lo contrario", asumiendo que el mensaje sería un texto de ayuda. Pero estoy seguro de que Werner puede descubrir qué hace esa línea y si la quiere :)
— Thomas

gracias, por supuesto! y por último, ¿cómo puedo desactivar los mensajes de error del script para que no se muestren en el shell?
— Abre el camino el

¿Te refieres a los errores que surgen de un programa en particular al que estás llamando? Puede poner > /dev/nully / o 2> /dev/nulldespués de eso enviar su salida estándar y / o flujos de error estándar al olvido.
— Thomas

4
Si considera que falta un argumento como algo malo (como que el script no puede funcionar correctamente), devuelva algo diferente a 0 ( exit 1). Existen otras convenciones sobre códigos de retorno / salida, que puede encontrar en línea rápidamente, pero el punto importante es que no debe ser 0, lo que indica éxito.
— Felix

25

Si solo está interesado en rescatar si falta un argumento en particular, la sustitución de parámetros es excelente:

#!/bin/bash
# usage-message.sh

: ${1?"Usage: $0 ARGUMENT"}
#  Script exits here if command-line parameter absent,
#+ with following error message.
#    usage-message.sh: 1: Usage: usage-message.sh ARGUMENT

11

Ejemplo

 if [ -z "$*" ]; then echo "No args"; fi

Resultado

No args

Detalles

-z es el operador unario para la longitud de la cadena es cero. $*son todos los argumentos. Las comillas son por seguridad y encapsulan múltiples argumentos si están presentes.

Utilice man bashy busque ( tecla / ) "unario" para más operadores como este.


7
Un problema (menor) con esto es que no distingue entre no pasar argumentos y pasar una cadena vacía como argumento. Eso puede ser importante en algunos contextos. Usando [$ # -eq 0] uno puede manejar ambos casos correctamente.
— Idelic

1
Ah, las sutilezas de la programación (ba) sh ... Por eso la odio.
— Thomas

1
pensar en -zcomo mizzing
— Ray Foss

4

Viejo, pero tengo motivos para volver a trabajar la respuesta ahora gracias a una confusión previa:

if [[ $1 == "" ]] #Where "$1" is the positional argument you want to validate 

 then
 echo "something"
 exit 0

fi

Esto hará eco de "Algo" si no hay un argumento posicional $ 1. Sin embargo, no valida que $ 1 contenga información específica.


$#es explícitamente el recuento entero del número de argumentos; será "0", y repetirá "algo" aunque no haya argumentos, o será un número positivo, y repetirá "algo" correctamente. Pero la verificación en sí nunca hará nada, independientemente de la entrada o la falta de entrada que use; siempre informará que $#contiene un valor. Entonces esto es completamente incorrecto y nunca funcionará como se afirma.
— eschwartz

¿Estás completamente seguro de eso? Tengo varios scripts que funcionan según lo previsto con este formato exacto. Al leer su respuesta, incluso volví a probar tanto por el partido como por la falta del mismo. $ # no contendrá un valor si no se especifica, si no hay un argumento posicional que coincida con lo que sea # en su escenario. No tiene sentido por qué bash asumiría un valor en un argumento posicional que no está allí.
— Ryan Smith

Pruebe echo $#como el contenido de un script /tmp/test.sh, luego ejecútelo en / bin / bash así como en / bin / sh (o / bin / dash y cualquier otra implementación de shell que tenga disponible. /tmp/test.shRepetirá "0" para la consola, como lo hará /bin/dash /tmp/test.sh. Por otro lado, /tmp/test.sh foohará eco de "1", y /tmp/test.sh first secondhará eco de "2".
— eschwartz

Según man bash, en la sección "Parámetros especiales", "El shell trata varios parámetros de manera especial. Estos parámetros solo pueden ser referenciados; no se permite su asignación", y "# Se expande al número de parámetros posicionales en decimal". También es un mandato de POSIX como se describe en pubs.opengroup.org/onlinepubs/9699919799/utilities/…
— eschwartz

Lo siento, parece que hubo una falta de comunicación. Quise decir # como marcador de posición para el argumento posicional específico (es decir, $ 2 si se refería al segundo argumento) no literal $ #. Después de revisar lo anterior, está absolutamente en lo cierto, un $ # literal siempre se resolverá con el número de argumentos. Disculpas por la confusión.
— Ryan Smith
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.