
Estou lendo o script bash e não entendo o que está acontecendo lá.
#!/bin/sh
[ x$1 = x ]
O que está acontecendo na segunda linha e o que [ x$1 = x ]
significa?
Responder1
Isso verifica se $1
está vazio, embora deva estar entre aspas (idêntico a [ -z "$1" ]
). Alguns shells muito antigos não lidavam com strings vazias adequadamente, então os escritores de scripts portáteis adotaram esse estilo de verificação. Não é necessário há décadas, mas as pessoas ainda fazem assim porque ainda fazem assim.
Responder2
Colchetes indicam umteste, portanto, [ x$1 = x]
sem if
ou algo semelhante não tem sentido, embora sintaticamente ok.
O objetivo é avaliar como verdadeiro se for x$1
expandido para x
e falso caso contrário, mas como não está entre aspas, se $1
for (por exemplo) "ei x", o shell verá x = x
, portanto, essa construção ainda não é segura.
O objetivo da x = x
verificação é determinar se uma variável está vazia. Uma maneira mais comum de fazer isso seria apenas usar aspas:
if [ "$1" = "" ]; then
Operadores de teste Bash -z
também -n
podem ser usados, mas são menos portáveis para outros tipos de shells. 1
O motivo das aspas, ou x$1
, é para que o lado esquerdo não se expanda para nada, o que seria um erro sintático:
if [ = x ] # No good!
if [ "" = "" ] # Okay.
if [ x = x ] # Also okay.
1. Na verdade, test
pode ser um utilitário independente, mas a maioria dos shells o implementa como um utilitário integrado; verifique a diferença entre which test
e type test
. No GNU/Linux man test
afirma se referir ao integrado, mas se você chamar (por exemplo) /usr/bin/test
, esse utilitário parece implementar os recursos documentados na página de manual, incluindo -z
e -n
.
Responder3
[ x$1 = x ]
Só faz sentido em zsh
. Isso compara a concatenação de x
com o primeiro argumento do script para x
. Portanto, o [
comando retorna verdadeiro se $1
estiver vazio ou não for fornecido.
[ $1 = "" ]
Não funcionaria porque, quando zsh
uma variável vazia não é citada em contextos de lista, ela se expande para nenhum argumento em vez de um argumento vazio, portanto, se $1
não estivesse definido ou vazio, o [
comando receberia apenas como argumentos [
, =
, a string vazia e ]
do qual não fazia sentido. [ -z "$1" ]
ou [ "$1" = "" ]
seria bom, como nos shells POSIX.
Em shells tipo Bourne/POSIX, [ x$1 = x ]
não faz sentido. Esse é o operador split+glob aplicado de alguma forma à concatenação de x
e ao primeiro argumento do script, esperando que o resultado and =
e x
constitua ]
uma expressão de teste válida para o [
comando.
Por exemplo, se o script recebesse um " = x -o x ="
argumento, [
receberia esses argumentos: [
, x
, =
, x
, -o
, x
, =
, x
, ]
, que [
seria entendido como comparação x
com x
e x
com x
e retornaria verdadeiro.
Se $1
fosse "* *"
, então o shell passaria para o [
comando a lista de arquivos no diretório atual cujo nome começa com x
(a expansão glob de x*
), depois a lista de arquivos não ocultos (expansão *
)... o que [
é improvável que seja capaz para fazer algum sentido. Os únicos casos em que isso faria algo sensato é se $1
não contiver caracteres curinga ou caracteres em branco.
Agora, o que você às vezes encontra é um código como:
[ "x$1" = x ]
Isso é usado para testar se $1
está vazio ou não definido.
A maneira normal de testar uma variável vazia ou não definida é:
[ -z "$1" ]
Mas isso falha para alguns valores $1
como =
em algumas implementações (não POSIX), [
como a incorporada no shell Bourne, encontrada /bin/sh
no Solaris 10 e anteriores ou em algumas versões antigas dash
(até 0.5.4) ou de sh
alguns BSDs.
Isso porque [
vê [
, -z
, =
e ]
reclama da falta de argumentos no =
operador binário em vez de entendê-lo como o -z
operador unário aplicado à =
string.
Da mesma forma, [ "$1" = "" ]
falha em algumas implementações de [
if $1
is !
ou (
.
Nessas [
implementações shell/:
[ "x$1" = x ]
é sempre um teste válido, independentemente do valor de $1
, assim como:
[ "" = "$1" ]
e:
[ -z "${1:+x}" ]
e
case $1 in "") ...; esac
Claro, se você quiser verificar se nenhum argumento foi fornecido, você faria:
[ "$#" -eq 0 ]
Ou seja, você verifica a quantidade de argumentos passados para o script.
Observe que hoje em dia, [ -z "$var" ]
é claramente especificado pelo POSIX e não pode falhar em [
implementações compatíveis (e bash
é [
e tem sido há décadas). Portanto, você deve poder confiar nele em sh ou bash
scripts POSIX.
Responder4
[ x$1 = x ]
é verdadeiro se $1
não estiver definido/nulo/vazio ou não.
Experimente você mesmo com:
TEST= ;[ x$TEST = x] && echo "TEST is unset"
e
TEST=lolz ;[ x$TEST = x ] && echo "TEST is unset"