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

La siguiente sintaxis bash verifica si param no está «t vacío:

 [[ ! -z $param ]] 

Por ejemplo:

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

Sin 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" 

«No soy cero «.

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

Comentarios

  • De man test: -z STRING - the length of STRING is zero. Si desea eliminar todos los espacios en $param, use ${param// /}
  • WOW no hay una función simple trim() incorporada a ¿Alguno * nix en absoluto? Tantos trucos diferentes para lograr algo tan simple …
  • @ADTC $ (sed ‘ s / ^ \ s + | \ s + $ // g ‘ < < < $ string) me parece bastante simple. ¿Por qué reinventar la rueda?
  • Porque podría ser más brillante
  • Solo notando que [[ ! -z $param ]] es equivalente a test ! -z $param.

Respuesta

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

la longitud de la cadena es cero

Es decir, una cadena que contiene solo espacios debe no sea cierto en -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 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 un cadena vacía.


El meollo 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), reemplaza todas las coincidencias. Debido a que el reemplazo está vacío, podemos omitir el valor final / y string:

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

El patrón se expande para producir un patrón como en la expansión de nombre de archivo. Parámetro se expande y la coincidencia más larga de patrón con su valor se reemplaza por cadena . Si el patrón comienza con «/», todas las coincidencias del patrón se reemplazan por cadena . Normalmente, solo se reemplaza la primera coincidencia. … Si cadena es nula, las coincidencias de patrón se eliminan y el patrón siguiente puede omitirse.

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

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

Comentarios

  • use sed dijeron … solo echo la variable que dijeron …
  • Hmm. Si es ${var/pattern/string}, entonces no debería ‘ ser [[ -z ${param/ /} ]] con el espacio entre las barras para ser el patrón y nada después para ser la cadena?
  • @JesseChisholm » Debido a que el reemplazo está vacío, podemos omitir el / final y el valor de cadena «; » Si cadena es nula, las coincidencias del patrón se eliminan y el siguiente patrón puede ser omitido. »
  • @MichaelHomer La respuesta [[ -z "${param// }" ]] seguramente se parece a la pattern está vacío y replacement string es un solo espacio. ¡AH! Lo veo ahora if pattern begins with a slash Me perdí esa parte. por lo que el patrón es / y la cadena se deja fuera y por lo tanto está vacía. Gracias.
  • nota de bash: si se ejecuta en set -o nounset (set -u), y param no está configurado (en lugar de nulo o lleno de espacios), esto generará un error de variable independiente. (set + u; …..) eximiría esta prueba.

Respuesta

La forma más fácil comprobar que una cadena solo contiene caracteres en un conjunto autorizado es comprobar 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 que no sea espacio. En bash, ksh o zsh:

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

«Consta solo de espacios» incluye el caso de una variable vacía (o no definida).

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

Hacer coincidir una cadena con un patrón con = dentro de [[ … ]] 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 de shell estándar 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 caracteres de espacio en blanco, 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, por ejemplo,

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

Comentarios

  • Esto es casi excelente – pero, hasta ahora, no responde a la pregunta como se le preguntó. Actualmente puede decirle la diferencia entre una variable de shell vacía o sin configurar y una que solo contiene espacios. Si acepta mi sugerencia, agregará el formulario de expansión de parámetros que aún no está incluido en ninguna otra respuesta que pruebe explícitamente una variable de shell para ver si está configurada, me refiero a ${var?not set}, pasando esa prueba y sobreviviendo aseguraría que una variable que coincida con su *) case produciría una respuesta definitiva, por ejemplo.
  • Corrección: esto, de hecho, respondería a la pregunta formulada originalmente, pero desde entonces se ha editado de tal manera que cambia fundamentalmente el significado de la pregunta y, por lo tanto, invalida su respuesta.
  • Necesita [[ $param = *[!\ ]* ]] en mksh.

Respuesta

POSIXly:

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 , desarmado :

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 A SCII, pero probablemente haya algunos más en su localidad; algunos sistemas incluirán el espacio que no se separa (cuando esté disponible), otros no). Si también desea caracteres de espaciado vertical (como nueva línea o avance de formulario), reemplace [:blank:] con [:space:].

Comentarios

  • POSIXly es ideal porque funcionará con el (posiblemente mejor) dash.
  • zsh parece tener un problema con [![:blank:]], genera :b es un modificador no válido. En sh y ksh emular, no se encuentra el evento de activación para [
  • @cuonglm, ¿qué probaste? var=foo zsh -c 'case ${var+x$var} in (x*[![:blank:]]*) echo x; esac' está bien para mí. El evento no encontrado sería solo para shells interactivos.
  • @St é phaneChazelas: Ah, claro, lo intenté con shells interactivos. El :b modificador inválido es un poco extraño.
  • @FranklinYu, en OS / X sh es construido con --enable-xpg-echo-default y --enable-strict-posix-default para ser compatible con Unix (lo que implica echo '\t' mostrando una pestaña).

Respuesta

La única razón restante para escribir una secuencia de comandos de shell, en lugar de una secuencia de comandos en un buen lenguaje de secuencias de comandos, si la portabilidad extrema es una preocupación primordial. El /bin/sh heredado es lo único que puede estar seguro de tener, pero Perl, por ejemplo, es más probable que esté disponible en varias plataformas que Bash. Por lo tanto, nunca escriba scripts de shell que utilicen funciones que no sean verdaderamente universales , y tenga en cuenta que varios proveedores de Unix propietarios congelaron su entorno de shell antes de POSIX.1-2001 .

Existe una forma portátil de realizar esta prueba, pero debes 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 integrado es en sí mismo muy portátil, pero confiar en él es mucho menos complicado que averiguar qué variante de echo tienes)

Comentarios

  • Eso ‘ es un poco complicado.La forma portátil habitual de probar si una cadena contiene ciertos caracteres es con case .
  • @Gilles No ‘ no creo ‘ s posible escribir un case glob para detecta una cadena que está vacía o contiene solo caracteres de espacio en blanco. (Sería fácil con una expresión regular, pero case no ‘ no usa expresiones regulares. La construcción en su respuesta ganó ‘ no funciona si te preocupan las nuevas líneas.)
  • Di espacios como ejemplo en mi respuesta porque ‘ es la pregunta solicitado. Es ‘ igualmente fácil de probar para los caracteres de espacio en blanco: case $param in *[![:space:]]*) …. Si desea probar IFS caracteres, puede usar el patrón *[$IFS]*.
  • @mikeserv De una manera realmente En serio script defensivo, estableces explícitamente IFS en <space><tab><newline> al principio y luego no vuelvas a tocarlo. Pensé que ‘ sería una distracción.
  • Con respecto a las variables en los patrones, creo que funciona en todas las versiones de Bourne y todos los shells POSIX; requeriría código adicional para detectar patrones de casos y desactivar la expansión de variables y no puedo ‘ pensar en una razón para hacerlo. Tengo un par de instancias en mi .profile que ha sido ejecutado por muchos shells Bourne. Por supuesto, [$IFS] ganó ‘ t hacer lo que se pretendía si IFS tiene ciertos valores no predeterminados valores (vacíos (o sin configurar), que contienen ], comenzando con ! o ^) .

Respuesta

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 

Comentarios

  • esto elimina cualquier carácter de espacio en blanco, no solo un solo espacio, ¿verdad? gracias

Responder

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

${name:?variable is empty} 

Comentarios

  • Creo que tu respuesta tiene una votación negativa porque » o contener espacios » no es cierto.
  • tenga cuidado, eso mata el shell actual. Es mejor ponerlo en un (: $ {subshell?}). Además, eso escribirá en stderr, probablemente desee redireccionar. Y más importante que evalúa el valor real de la variable ‘ si no está desarmado o es nulo. Si hay ‘ un comando allí, simplemente lo ejecuta. Es ‘ mejor ejecutar esa prueba en :.
  • cómo eliminará el shell. y también puede probar esto, primero defina name=aaaa luego ejecute este comando echo ${name:?variable is empty} imprimirá el valor del nombre de la variable y ahora ejecute este comando echo ${name1:?variable is empty} imprimirá -sh: name1: variable is empty
  • Sí – echo ${name:?variable is empty} evaluará el valor no nulo de $name o matará el shell. Entonces, por la misma razón, usted no ‘ no prompt > $randomvar tampoco debe ${var?} – si hay ‘ un comando allí, ‘ probablemente se ejecutará, y usted no ‘ t sé lo que es. Un shell interactivo no ‘ t tiene que salir, por eso el suyo no ‘ t. Aún así, si desea ver algunas pruebas, hay muchas aquí. . Este no es ‘ t tan largo …

Respuesta

El código que publicaste [[ ! -z $param ]] && echo "I am not zero" se imprimirá I am not zero si param no está definido / no está definido o está 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:

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

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

Este resultado expandido se prueba si tiene una longitud 0.

  • Si el resultado está vacío, entonces la variable estaba vacía o
  • eliminando los espacios iniciales lo dejó 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 caracteres. Para incluir también pestañas, coloque una pestaña explícita dentro de la expresión entre corchetes:

 [ -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" 

Respuesta

Para verificar si la variable solo tiene espacios, incluso en una variable de varias líneas , prueba esto:

[[ $var = *[$" \t\n"]* ]] 

O con xargs:

[[ -z $(echo $var | xargs) ]] 

O con sed:

[[ -z $(sed "/^$/d" <<< $var) ]] 

Responder

Pruebe esto:

$ [[ -z \`echo $n\` ]] && echo zero zero 

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *