script bash [x $ 1 = x]

21

Estoy leyendo un script bash, no entiendo lo que está pasando allí.

#!/bin/sh
[ x$1 = x ] 

¿Qué está pasando en la segunda línea y qué [ x$1 = x ] significa?

Mover
fuente

Respuestas:

27

Eso comprueba que $1está vacío, aunque debe citarse (idéntico a [ -z "$1" ]). Algunos shells muy antiguos no manejaban las cadenas vacías correctamente, por lo que los escritores de scripts portátiles adoptaron este estilo de verificación. No ha sido necesario durante décadas, pero la gente todavía lo hace así porque la gente todavía lo hace de esa manera.

Kevin
fuente
Sí, ya no deberías hacerlo así y adoptar un estilo más moderno. A menos que esté trabajando en un PDP11.
MacLemon
44
No se trata tanto de cadenas vacías. [ x$1 = x ]sigue siendo incorrecto, pero [ "x$1" = x ]sería para shells que tienen un problema donde $1está !o (o -n... [ "" = "$1" ]y case $1 in "")también estaría bien.
Stéphane Chazelas
2
@ MacLemon, no hay necesidad de retroceder tanto. [ -z "$1" ]y [ "$1" = "" ]todavía no funciona con / bin / sh de Solaris 10, el primero con dash-0.5.4.
Stéphane Chazelas
1
¡+1 extra para la última oración!
Glenn Jackman
1
@glennjackman, esa última oración es incorrecta. Solaris 10 sigue siendo la versión más ampliamente implementada de Solaris y [ "$1" = "" ]todavía no funciona con ella /bin/sh(aunque querría usarla /usr/xpg4/bin/shallí, no /bin/sh). el guión se solucionó al respecto en enero de 2009.
Stéphane Chazelas
8

Los corchetes indican una prueba , entonces [ x$1 = x]sin ifo algo similar no tiene sentido, aunque sintácticamente está bien.

Está destinado a evaluar a verdadero si se x$1expande a x, y falso de lo contrario, pero dado que no está entre comillas, si $1es (por ejemplo) "hey x", el shell verá x = x, por lo que esta construcción aún no es segura.

El propósito de la x = xverificación es determinar si una variable está vacía. Una forma más común de hacer esto sería simplemente usar comillas:

if [ "$1" = "" ]; then

Operadores de prueba del golpe -zy -ntambién se pueden utilizar, pero son menos portátiles a otros tipos de proyectiles. 1

La razón de las comillas, o el x$1, es que el lado izquierdo no se expande a nada, lo que sería un error sintáctico:

if [  = x ]  # No good!
if [ "" =  "" ] # Okay.
if [ x = x ] # Also okay.

1. En realidad, testpuede ser una utilidad independiente, pero la mayoría de los shells lo implementan como una función incorporada; compruebe la diferencia entre which testy type test. En GNU / Linux se man testafirma que se refiere a la función integrada, pero si llama (por ejemplo) /usr/bin/test, esa utilidad parece implementar las características documentadas en la página del manual, incluyendo -zy -n.

encerrada dorada
fuente
1
[ x$1 = x ]también evaluará a verdadero si $1es por ejemplo " -o x". Tratar sh -xc '[ x$1 = x ] && echo yes' sh ' -o x'. [ x$1 = x ]está mal y no tiene sentido.
Stéphane Chazelas
@ StéphaneChazelas Gracias SC - editado (segundo párrafo).
Ricitos
no necesita ifusar test, puede usarlo antes &&, ||o después whileo examinar el resultado usando$?
Jasen
8
[ x$1 = x ]

Solo tiene sentido zsh. Eso compara la concatenación de xcon el primer argumento del guión a x. Entonces, el [comando devuelve verdadero si $1está vacío o no se proporciona.

[ $1 = "" ]

¿No trabajo porque, en zshcuando una variable de vacío no es citado en contextos de la lista, que se expande a ningún argumento en absoluto en lugar de un argumento vacío, por lo que si $1fuese definido o vacía, el [comando sería sólo reciben como argumentos [, =la cadena vacía y de lo ]que no podía tener sentido. [ -z "$1" ]o [ "$1" = "" ]estaría bien, como en los shells POSIX.

En los shells tipo Bourne / POSIX, [ x$1 = x ]no tiene sentido. Ese es el operador split + glob que se aplica de alguna manera a la concatenación xy al primer argumento del script con la esperanza de que el resultado =yy x, y ]compongan una expresión de prueba válida para el [comando.

Por ejemplo, si el guión se aprobó un " = x -o x ="argumento, [recibiría esos argumentos: [, x, =, x, -o, x, =, x, ], que [entendería como la comparación xcon el xy xcon xy devolver cierto.

Si $1fuera así "* *", el shell pasaría al [comando la lista de archivos en el directorio actual cuyo nombre comienza con x(la expansión global de x*), luego la lista de archivos no ocultos (expansión *) ... que [es poco probable que pueda para que tenga sentido. Los únicos casos en que eso haría algo sensato es si $1no contiene comodines o caracteres en blanco.

Ahora, lo que a veces encuentras es código como:

[ "x$1" = x ]

Eso se usa para probar si $1está vacío o sin configurar.

La forma normal de probar una variable vacía o no establecida es:

[ -z "$1" ]

Pero eso falla para algunos valores de $1like =en algunas [implementaciones (no POSIX) como la incorporada en el shell Bourne como se encuentra /bin/shen Solaris 10 y antes o algunas versiones antiguas de dash(hasta 0.5.4) o la shde algunos BSD.

Eso es porque [ve [, -z, =, ]y se queja de que faltan argumentos para el =operador binario en lugar de entenderlo como el -zoperador unitario aplicado a la =cadena.

Del mismo modo, [ "$1" = "" ]falla para algunas implementaciones de [if $1is !or (.

En esas shell / [implementaciones:

[ "x$1" = x ]

siempre es una prueba válida independientemente del valor de $1, también lo son:

[ "" = "$1" ]

y:

[ -z "${1:+x}" ]

y

case $1 in "") ...; esac

Por supuesto, si desea comprobar que no se proporciona ningún argumento, haría:

[ "$#" -eq 0 ]

Es decir, verifica el número de argumentos pasados ​​al script.

Tenga en cuenta que hoy en día, [ -z "$var" ]POSIX lo especifica claramente y no puede fallar en [implementaciones conformes (y bash's [es y ha sido por décadas). Por lo tanto, debería poder confiar en él en POSIX sh o bashscripts.

Stéphane Chazelas
fuente
0

x$1está concatenando dos cadenas xy $1si $ 1 está vacío, x $ 1 es igual a x, y como resultado [x $ 1 = x] será verdadero. x = yse usa para comparar cadenas en sh

harish.venkat
fuente
2
No x$1no se cita, por lo que se realiza la división y el bloqueo en esos.
Stéphane Chazelas
0

[ x$1 = x ]es verdadero si $1está desarmado / nulo / vacío o no.
Pruébalo con:
TEST= ;[ x$TEST = x] && echo "TEST is unset"
y
TEST=lolz ;[ x$TEST = x ] && echo "TEST is unset"

xx4h
fuente
1
[ x$1 = x ]También es cierto si $1es por ejemplo " -o x". Tratar sh -xc '[ x$1 = x ] && echo yes' sh ' -o x'. [ x$1 = x ]está mal y no tiene sentido.
Stéphane Chazelas