script bash [x $ 1 = x]

21

Eu estou lendo o script bash Eu 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?

    
por Bob 11.06.2014 / 19:43

5 respostas

24

Isso verifica que $1 está vazio, embora deva ser citado (idêntico a [ -z "$1" ] ). Algumas shells muito antigas não lidavam com strings vazias corretamente, então os escritores de scripts portáveis adotaram esse estilo de verificação. Não tem sido necessário por décadas, mas as pessoas ainda fazem isso dessa forma porque as pessoas ainda assim fazem isso.

    
por 11.06.2014 / 20:01
8

Os colchetes indicam um teste , por isso [ x$1 = x] sem if ou algo semelhante é sem sentido, embora sintaticamente ok.

Ele deve ser avaliado como verdadeiro se x$1 se expandir para x e falso caso contrário, mas como não é citada, se $1 for (por exemplo) "hey x", o shell verá x = x , então essa construção ainda não é segura.

A finalidade da verificação x = x é determinar se uma variável está vazia. Uma maneira mais comum de fazer isso seria usar apenas aspas:

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

Os operadores de teste de bash -z e -n também podem ser usados, mas são menos portáveis para outros tipos de shells. 1

A razão para as aspas, ou o 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 autônomo, mas a maioria dos shells o implementam como um built-in; verifique a diferença entre which test e type test . No GNU / Linux man test alega se referir ao built-in, mas se você chamar (por exemplo) /usr/bin/test , esse utilitário parece implementar os recursos documentados na página man, incluindo -z e -n . / sup>

    
por 11.06.2014 / 20:04
6
[ x$1 = x ]

Faz sentido apenas em zsh . Isso compara a concatenação de x com o primeiro argumento do script para x . Portanto, o comando [ retornará verdadeiro se $1 estiver vazio ou não for fornecido.

[ $1 = "" ]

Não funcionaria porque, em zsh quando 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 estiver definido ou vazio, [ comando receberia apenas como argumentos [ , = , a string vazia e ] dos quais não fazia sentido. [ -z "$1" ] ou [ "$1" = "" ] seria OK, como em shells POSIX.

Em shells do tipo Bourne-like / POSIX, [ x$1 = x ] não faz sentido. Esse é o operador de divisão + glob aplicado de alguma forma à concatenação de x e o primeiro argumento do script esperando que o resultado e = e x e ] constituam uma expressão de teste válida para o [ comando.

Por exemplo, se o script tiver recebido um argumento " = x -o x =" , [ receberia esses argumentos: [ , x , = , x , -o , x , = , x , ] , que [ entenderia como comparando x com x e x com x e retornará verdadeiro.

Se $1 fosse "* *" , 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* ). lista de arquivos não ocultos (expansão * ) ... que [ provavelmente não conseguirá ter sentido. Os únicos casos em que isso faria qualquer coisa sensata são se $1 não contiver caracteres curinga ou 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 em alguns valores de $1 como = em algumas implementações (não-POSIX) [ , como a integrada em um shell Bourne, como /bin/sh no Solaris 10 e antes ou em algum antigo versões de dash (até 0.5.4) ou sh de alguns BSDs.

Isso porque [[ , -z , = , ] e reclama sobre argumentos ausentes para o operador = binário em vez de entendê-los como o operador -z unário aplicado ao = string.

Da mesma forma, [ "$1" = "" ] falha em algumas implementações de [ se $1 for ! ou ( .

Nestas implementações shell / [ :

[ "x$1" = x ]

é sempre um teste válido, independentemente do valor de $1 , portanto:

[ "" = "$1" ]

e:

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

e

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

Claro, se você quiser verificar se nenhum argumento é fornecido, faça o seguinte:

[ "$#" -eq 0 ]

Ou seja, você verifica o número de argumentos passados para o script.

Note que hoje em dia, [ -z "$var" ] é claramente especificado por POSIX e não pode falhar em conformidade com [ implementations (e bash [ é e tem sido por décadas). Então você deve poder confiar nele nos scripts POSIX sh ou bash .

    
por 17.06.2014 / 00:18
0

x$1 está concatenando duas strings x e $1 e se $ 1 estiver vazio, x $ 1 será igual a x e [x $ 1 = x] será verdadeiro como resultado. x = y é usado para comparar strings em sh

    
por 11.06.2014 / 20:01
0

[ x$1 = x ] é verdadeiro se $1 não estiver definido / nulo / vazio ou não.
Tente você mesmo com:
TEST= ;[ x$TEST = x] && echo "TEST is unset"
e TEST=lolz ;[ x$TEST = x ] && echo "TEST is unset"

    
por 11.06.2014 / 20:02

Tags