Verifique la existencia del argumento de entrada en un script de shell Bash

Necesito verificar la existencia de un argumento de entrada. Tengo el siguiente guion

if [ "$1" -gt "-1" ]
  then echo hi
fi

yo obtengo

[: : integer expression expected

¿Cómo verifico primero el argumento de entrada 1 para ver si existe?

preguntado el 26 de junio de 11 a las 02:06

11 Respuestas

Es:

if [ $# -eq 0 ]
  then
    echo "No arguments supplied"
fi

El $# La variable le dirá el número de argumentos de entrada que se pasó el script.

O puede verificar si un argumento es una cadena vacía o no como:

if [ -z "$1" ]
  then
    echo "No argument supplied"
fi

El -z El interruptor probará si la expansión de "$1" es una cadena nula o no. Si es una cadena nula, se ejecuta el cuerpo.

Respondido el 28 de enero de 21 a las 08:01

Me gusta hacerlo de esta manera, en sintaxis concisa y aún POSIX aceptable. [ -z "$1" ] && echo "No argument supplied" Prefiero frases de una sola línea, ya que son más fáciles para mí; y también es más rápido verificar el valor de salida, en comparación con usar if - JM Becker

Probablemente quieras agregar un exit 1 al final de sus ecos dentro del bloque if cuando se requiere el argumento para que funcione el script. Obvio, pero digno de mención por su integridad. - sanford

Es posible, aunque rara vez útil, que el primer argumento se inicialice pero esté vacío; programname "" secondarg third. $# check comprueba sin ambigüedades el número de argumentos. - triples

Para un novato, especialmente para alguien que no tiene experiencia en guiones, también es importante mencionar algunas peculiaridades sobre estas cosas. También podría haber mencionado que necesitamos un espacio después de la llave de apertura y cierre. De lo contrario, las cosas no funcionan. Yo mismo soy un novato en scripting (vengo de origen C) y lo encontré de la manera más difícil. Fue solo cuando decidí copiar todo "tal cual" que las cosas funcionaron para mí. Fue entonces cuando me di cuenta de que tenía que dejar un espacio después del tirante de apertura y antes del de cierre. - altoencarne

y para argumentos opcionales if [ ! -z "$1" ]; then ... - gcb

Es mejor demostrar de esta manera

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

Normalmente, debe salir si tiene muy pocos argumentos.

respondido 14 nov., 19:16

No, no lo es: esto tiene exit 1 que normalmente desea y utiliza el [[ ]] prueba cuál (iirc) suele ser más razonable. Entonces, para las personas que copian y pegan código a ciegas, esta es la mejor respuesta. - pastor

Para saber más sobre la diferencia entre [] y [[]], consulte stackoverflow.com/questions/3427872/… - Sebastián Grignoli

En algunos casos, debe verificar si el usuario pasó un argumento al script y, si no es así, volver a un valor predeterminado. Como en el siguiente guión:

scale=${2:-1}
emulator @$1 -scale $scale

Aquí si el usuario no ha pasado scale como segundo parámetro, lanzo el emulador de Android con -scale 1 por defecto ${varname:-word} es un operador de expansión. También hay otros operadores de expansión:

  • ${varname:=word} que conjuntos lo indefinido varname en lugar de devolver el word valor;
  • ${varname:?message} que o bien regresa varname si está definido y no es nulo o imprime el message y aborta el script (como el primer ejemplo);
  • ${varname:+word} que regresa word sólo si varname está definido y no es nulo; devuelve nulo en caso contrario.

respondido 07 mar '19, 08:03

El ejemplo anterior parece usar ${varname?message}. Es el extra : un error tipográfico o cambia el comportamiento? - octubre

Eki, el ":" es un comando incorporado y una abreviatura de / bin / true en este ejemplo. Representa un comando de no hacer nada que básicamente ignora los argumentos que se le proporcionan. Es esencial en esta prueba para evitar que el intérprete intente ejecutar el contenido de "$ varname" (lo que ciertamente NO desea que suceda). También vale la pena señalar; puede probar tantas variables con este método como desee. Y todo con mensajes de error específicos. es decir : ${1?"First argument is null"} ${2?"Please provide more than 1 argument"} - fácil de usar

Tratar:

 #!/bin/bash
 if [ "$#" -eq  "0" ]
   then
     echo "No arguments supplied"
 else
     echo "Hello world"
 fi

respondido 25 nov., 15:11

¿Por qué necesita comillas dobles para $# y 0? - user13107

No hay problema si usamos sin comillas dobles como $ # y 0 - Ranjithkumar T

en windows, mingw este es el único camino a seguir. - Lajos Mészaros

Esta respuesta proporciona un excelente punto de partida para un guión que acabo de hacer. Gracias por mostrar el else, también. - Chris K

@ user13107 las variables entre comillas dobles en bash evitan el globbing (es decir, expandir los nombres de archivo como foo*) y división de palabras (es decir, dividir el contenido si el valor contiene espacios en blanco). En este caso no es necesario cotizar $# porque ambos casos no se aplican. Citando el 0 Tampoco es necesario, pero algunas personas prefieren citar valores ya que en realidad son cadenas y eso lo hace más explícito. - Dennis

Otra forma de detectar si se pasaron argumentos al script:

((!$#)) && echo No arguments supplied!

Tenga en cuenta que (( expr )) hace que la expresión se evalúe según las reglas de Aritmética de Shell.

Para salir en ausencia de argumentos, se puede decir:

((!$#)) && echo No arguments supplied! && exit 1

Otra (análogo) forma de decir lo anterior sería:

let $# || echo No arguments supplied

let $# || { echo No arguments supplied; exit 1; }  # Exit if no arguments!

help let dice:

let: let arg [arg ...]

  Evaluate arithmetic expressions.

  ...

  Exit Status:
  If the last ARG evaluates to 0, let returns 1; let returns 0 otherwise.

Respondido el 07 de enero de 16 a las 16:01

-1 este podría ser el peor método para validar la existencia de un argumento .. además puede desencadenar la sustitución del historial y potencialmente hacer cosas malas. - fácil de usar

en lugar de exit que mata mi proceso zsh, utilizo return que no lo mata - Timo

Por qué ((!$#)) ¿Desencadenar la sustitución de la historia? - zhro

Solo porque hay un punto más base para señalar, agregaré que simplemente puede probar que su cadena es nula:

if [ "$1" ]; then
  echo yes
else
  echo no
fi

Del mismo modo, si está esperando un recuento de argumentos, simplemente pruebe su último:

if [ "$3" ]; then
  echo has args correct or not
else
  echo fixme
fi

y así sucesivamente con cualquier arg o var

Respondido 02 ago 18, 22:08

A menudo uso este fragmento para scripts simples:

#!/bin/bash

if [ -z "$1" ]; then
    echo -e "\nPlease call '$0 <argument>' to run this command!\n"
    exit 1
fi

Respondido el 29 de diciembre de 17 a las 17:12

Entonces, esto se debe usar si solo necesita un argumento. - Danijel

@Danijel No, esto está probando si hay un argumento en la primera posición. Puede tener un argumento de $ 2 o $ 3 ($ 0 es el nombre del script que se está ejecutando). Esto simplemente ignora cualquier otro argumento pasado. - Josías

Si desea verificar si el argumento existe, puede verificar si el número de argumentos es mayor o igual que el número de su argumento de destino.

El siguiente script demuestra cómo funciona esto

prueba.sh

#!/usr/bin/env bash

if [ $# -ge 3 ]
then
  echo script has at least 3 arguments
fi

produce la siguiente salida

$ ./test.sh
~
$ ./test.sh 1
~
$ ./test.sh 1 2
~
$ ./test.sh 1 2 3
script has at least 3 arguments
$ ./test.sh 1 2 3 4
script has at least 3 arguments

Respondido el 20 de junio de 20 a las 10:06

Como pequeño recordatorio, los operadores de prueba numéricos en Bash solo funcionan con enteros (-eq, -lt, -ge, Etc.)

Me gusta asegurarme de que mis $ vars sean entradas por

var=$(( var + 0 ))

antes de probarlos, solo para defenderme contra el error "[: integer arg required".

respondido 09 nov., 15:15

Buen truco, pero tenga en cuenta: debido a la incapacidad de bash para manejar flotantes en aritmética, este método puede causar un error de sintaxis y devolver un valor distinto de cero, lo que sería un obstáculo donde errexit está habilitado. var=$(printf "%.0f" "$var") puede manejar flotadores pero sufre de la salida distinta de cero cuando se le da una cadena. Si no le importa un awk, este método que utilizo parece ser el más robusto para hacer cumplir un número entero: var=$(<<<"$var" awk '{printf "%.0f", $0}'). Si var no está establecido, el valor predeterminado es "0". Si var es un flotante, se redondea al número entero más cercano. Los valores negativos también están bien para usar. - fácil de usar

validación de la función bash de una línea

myFunction() {

    : ${1?"forgot to supply an argument"}
    if [ "$1" -gt "-1" ]; then
        echo hi
    fi

}

agregar el nombre de la función y el uso

myFunction() {

    : ${1?"forgot to supply an argument ${FUNCNAME[0]}() Usage:  ${FUNCNAME[0]} some_integer"}
    if [ "$1" -gt "-1" ]; then
        echo hi
    fi

}

agregar validación para verificar si es entero

para agregar validación adicional, por ejemplo para verificar si el argumento pasado es un número entero, modifique la validación un trazador de líneas para llamar a una función de validación:

: ${1?"forgot to supply an argument ${FUNCNAME[0]}() Usage:  ${FUNCNAME[0]} some_integer"} && validateIntegers $1 || die "Must supply an integer!"

luego, construya una función de validación que valide el argumento, devolviendo 0 en caso de éxito, 1 en caso de error y una función de troquel que aborta el script en caso de error

validateIntegers() {

    if ! [[ "$1" =~ ^[0-9]+$ ]]; then
        return 1 # failure
    fi
    return 0 #success

}

die() { echo "$*" 1>&2 ; exit 1; }

Aún más simple: solo use set -u

set -u se asegura de que cada variable a la que se hace referencia se establezca cuando se usa, así que solo configúrela y olvídese

myFunction() {
    set -u
    if [ "$1" -gt "-1" ]; then
        echo hi
    fi

}

Respondido el 31 de enero de 20 a las 21:01

En mi caso, la única solución de trabajo para verificar si ultimos argumentos existe es:

if [[ "$7" == '' ]] ; then
  echo "error"
  exit
fi

Respondido el 22 de Septiembre de 20 a las 16:09

Esto no es true. $7 es el séptimo argumento (el octavo si cuenta $0 que es el nombre del script), por lo que esto no verifica si existe el último argumento, verifica si existe el séptimo argumento. - Kevin G.

Estoy de acuerdo en que esta no es una solución a la pregunta y una solución subóptima para un problema diferente (y probablemente evitable). Siete argumentos posicionales parecen pesados. Además, exit sin estado de salida devolverá el estado de salida de echo "error", que espero que sea cero. Recomendar shellcheck y set -euo pipefail. Voy a parar ahora ... - Jack Wasey

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.