desarrollo-web-br-bd.com

¿Cómo puedo probar si una variable está vacía o contiene solo espacios?

La siguiente sintaxis bash verifica si param no está vacía:

 [[ !  -z  $param  ]]

Por ejemplo:

param=""
[[ !  -z  $param  ]] && echo "I am not zero"

No hay salida y está bien.

Pero cuando param está vacío, excepto por uno (o más) caracteres de espacio, entonces el caso es diferente:

param=" " # one space
[[ !  -z  $param  ]] && echo "I am not zero"

Se emite "No soy cero".

¿Cómo puedo cambiar la prueba para considerar variables que contienen solo caracteres de espacio como vacías?

261
maihabunash

Primero, tenga en cuenta que -z test es explícitamente para:

la longitud de la cuerda es cero

Es decir, una cadena que contiene solo espacios debe no ser verdadera bajo -z, porque tiene una longitud distinta de cero.

Lo que desea es eliminar los espacios de la variable usando expansión del parámetro de reemplazo de patrón :

[[ -z "${param// }" ]]

Esto expande la variable param y reemplaza todas las coincidencias del patrón (un solo espacio) con nada, por lo que una cadena que solo tiene espacios se expandirá a una cadena vacía.


El detalle de cómo funciona es que ${var/pattern/string} reemplaza la primera coincidencia más larga de pattern con string. Cuando pattern comienza con / (como arriba) luego reemplaza ¡todos las coincidencias. Como el reemplazo está vacío, podemos omitir el final / y el valor string:

$ {parámetro/patrón/cadena}

El patrón se expande para producir un patrón al igual que en la expansión de nombre de archivo. ¡Parámetro se expande y la coincidencia más larga de patrón contra su valor se reemplaza con cadena. Si ¡patrón comienza con ‘/’, todas las coincidencias de ¡patrón se reemplazan con cadena. Normalmente solo se reemplaza el primer partido. ... Si string es nulo, las coincidencias de pattern se eliminan y el/following pattern puede omitirse.

Después de todo eso, terminamos con ${param// } para eliminar todos los espacios.

Tenga en cuenta que aunque está presente en ksh (donde se originó), zsh y bash, esa sintaxis no es POSIX y no debe usarse en los scripts sh.

304
Michael Homer

La manera fácil de verificar que una cadena solo contenga caracteres en un conjunto autorizado es probar la presencia de caracteres no autorizados. Por lo tanto, en lugar de probar si la cadena solo contiene espacios, pruebe si la cadena contiene algún carácter distinto del espacio. En bash, ksh o zsh:

if [[ $param = *[!\ ]* ]]; then
  echo "\$param contains characters other than space"
else
  echo "\$param consists of spaces only"
fi

“Consiste solo en espacios” incluye el caso de una variable vacía (o no establecida).

Es posible que desee probar cualquier carácter de espacio en blanco. Utilizar [[ $param = *[^[:space:]]* ]] para usar la configuración regional o la lista explícita de caracteres de espacio en blanco que desea probar, p. [[ $param = *[$' \t\n']* ]] para probar el espacio, la pestaña o la nueva línea.

Hacer coincidir una cadena con un patrón con = dentro [[ … ]] es una extensión ksh (también presente en bash y zsh). En cualquier estilo Bourne/POSIX, puede usar la construcción case para hacer coincidir una cadena con un patrón. Tenga en cuenta que los patrones estándar de Shell usan ! para negar un conjunto de caracteres, en lugar de ^ como en la mayoría de las sintaxis de expresiones regulares.

case "$param" in
  *[!\ ]*) echo "\$param contains characters other than space";;
  *) echo "\$param consists of spaces only";;
esac

Para probar los espacios en blanco, el $'…' la sintaxis es específica de ksh/bash/zsh; puede insertar estos caracteres en su secuencia de comandos literalmente (tenga en cuenta que una nueva línea tendrá que estar entre comillas, ya que la barra invertida + nueva línea se expande a nada), o generarlos, p.

whitespace=$(printf '\n\t ')
case "$param" in
  *[!$whitespace]*) echo "\$param contains non-whitespace characters";;
  *) echo "\$param consists of whitespace only";;
esac

POSIXY:

case $var in
  (*[![:blank:]]*) echo '$var contains non blank';;
  (*) echo '$var contains only blanks or is empty or unset'
esac

Para diferenciar entre en blanco, no en blanco, vacío, sin definir:

case ${var+x$var} in
  (x) echo empty;;
  ("") echo unset;;
  (x*[![:blank:]]*) echo non-blank;;
  (*) echo blank
esac

[:blank:] es para caracteres de espaciado horizontal (espacio y tabulación en ASCII, pero probablemente haya algunos más en su ubicación; algunos sistemas incluirán el espacio que no se rompe (donde esté disponible), otros no). Si también desea caracteres de espaciado vertical (como nueva línea o avance de formulario), reemplace [:blank:] con [:space:].

22
Stéphane Chazelas

La única razón restante para escribir un script de Shell, en lugar de un script en un lenguaje de script bueno, es si la portabilidad extrema es una preocupación primordial. El legado /bin/sh es lo único que puede estar seguro de que tiene, pero Perl, por ejemplo, es más probable que esté disponible multiplataforma que Bash. Por lo tanto, nunca escriba scripts de Shell que usen características que no son verdaderamente universales - y tenga en cuenta que varios proveedores propietarios de Unix congelaron su entorno Shell antes de POSIX.1-2001 .

Hay una forma portátil de hacer esta prueba, pero debe usar tr:

[ "x`printf '%s' "$var" | tr -d "$IFS"`" = x ]

(El valor predeterminado de $IFS, convenientemente, es un espacio, una pestaña y una nueva línea.)

(El printf incorporado es en sí mismo muy portátil, pero confiar en él es mucho menos complicado que descubrir qué variante de echo tiene).

5
zwol
if [[ -n "${variable_name/[ ]*\n/}" ]]
then
    #execute if the the variable is not empty and contains non space characters
else
    #execute if the variable is empty or contains only spaces
fi
5
Guru

El código que publicaste [[ ! -z $param ]] && echo "I am not zero" imprimirá I am not zero si param está desarmado/indefinido o vacío (en bash, ksh y zsh).

Para también imprimir si param contiene solo espacios (eliminar espacios), POSIXly (para una gama más amplia de shells):

 [   -z "${param#"${param%%[! ]*}"}"   ] && echo "empty"

Explicación:

  • UNA ${param# … } elimina un texto inicial.
  • Ese texto principal viene dado por: ${param%%[! ]*}
  • Que se expande a todos los espacios antes cualquier sin espacio carácter, es decir, todos los espacios iniciales.

El resultado final de toda la expansión es que todos los espacios iniciales se eliminan.

Este resultado ampliado se prueba si es de longitud 0.

  • Si el resultado está vacío, entonces la variable estaba vacía o
  • eliminar los espacios iniciales lo hizo vacío.

Por lo tanto, si la prueba es verdadera, la variable ya estaba vacía o solo tenía espacios dentro.


El concepto es fácil de extender a más tipos de personajes. Para incluir también pestañas, coloque una pestaña explícita dentro de la expresión de paréntesis:

 [ -z "${param#"${param%%[!     ]*}"}" ] && echo "empty"

o use una variable con los caracteres que necesita eliminar:

 var=$' \t'                                    # in ksh, bash, zsh
 [ -z "${param#"${param%%[!$var]*}"}" ] && echo "empty"

o puede usar alguna "expresión de clase de caracteres" POSIX (en blanco significa espacio y tabulación):

 [ -z "${param#"${param%%[![:blank:]]*}"}" ] && echo "empty"
1
Isaac

Para probar si la variable está vacía o contiene espacios, también puede usar este código:

${name:?variable is empty}
1
pratik