script do bash [x $ 1 = x]

21

Estou lendo o script bash, 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?

Prumo
fonte

Respostas:

27

Isso verifica que $1está vazio, embora deva ser citado (idêntico a [ -z "$1" ]). Alguns shells muito antigos não lidavam com seqüências de caracteres vazias corretamente, 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 dessa maneira porque as pessoas ainda fazem dessa maneira.

Kevin
fonte
Sim, você não deve mais fazer isso dessa maneira e adotar um estilo mais moderno. A menos que você esteja trabalhando em um PDP11.
MacLemon
4
Não é tanto sobre cordas vazias. [ x$1 = x ]ainda está incorreto, mas [ "x$1" = x ]seria para as conchas que têm um problema em que $1é !ou (ou -n.... [ "" = "$1" ]e case $1 in "")também seria bom.
Stéphane Chazelas
2
@ MacLemon, não há necessidade de ir tão longe. [ -z "$1" ]e [ "$1" = "" ]ainda não funciona com o / bin / sh do Solaris 10, o primeiro com o traço-0.5.4.
Stéphane Chazelas
1
+1 extra para a última frase!
Glenn Jackman
1
@glennjackman, essa última frase está incorreta. O Solaris 10 ainda é a versão mais amplamente implantada do Solaris e [ "$1" = "" ]ainda não funciona com ela /bin/sh(embora você queira usá-la /usr/xpg4/bin/sh/bin/sh). o traço foi corrigido nesse sentido em janeiro de 2009.
Stéphane Chazelas
8

Colchetes indicam um teste ; portanto, [ x$1 = x]sem ifou algo semelhante não faz sentido, embora sintaticamente ok.

Ele serve para avaliar se true se x$1expande para xe false em caso contrário, mas como não é citado, se $1for (por exemplo) "ei x", o shell verá x = x, portanto essa construção ainda não é segura.

O objetivo da x = xverificação é 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 Bash -ze -ntambém podem ser usados, mas são menos portáteis para outros tipos de cascas. 1 1

O motivo das aspas, ou o x$1, é para que o lado esquerdo não se expanda a nada, o que seria um erro sintático:

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

1. Na verdade, testpode ser um utilitário independente, mas a maioria dos shells o implementa como um built-in; verifique a diferença entre which teste type test. No GNU / Linux, man testalega-se ao built-in, mas se você chamar (por exemplo) /usr/bin/test, esse utilitário parece implementar os recursos documentados na página de manual, incluindo -ze -n.

Cachinhos Dourados
fonte
1
[ x$1 = x ]também avaliará se $1é verdade, por exemplo " -o x". Tente sh -xc '[ x$1 = x ] && echo yes' sh ' -o x'. [ x$1 = x ]está errado e não faz sentido.
Stéphane Chazelas
@ StéphaneChazelas Obrigado SC - editado (segundo parágrafo).
Goldilocks
você não precisa ifpara uso test, você pode usá-lo antes &&, ||ou depois whileou examinar o resultado usando$?
Jasen
8
[ x$1 = x ]

Só faz sentido zsh. Isso compara a concatenação de xcom o primeiro argumento do script para x. Portanto, o [comando retorna true se $1estiver vazio ou não for fornecido.

[ $1 = "" ]

Não iria funcionar porque, zshquando uma variável vazia não é citado em contextos da lista, ele se expande para nenhum argumento em tudo, em vez de um argumento vazio, por isso, se $1foram unset ou vazio, o [comando seria só recebem como argumentos [, =a string vazia e do ]qual não fazia sentido. [ -z "$1" ]ou [ "$1" = "" ]seria bom, como nos shell do POSIX.

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

Por exemplo, se o script foi passado um " = x -o x ="argumento, [iria receber esses argumentos: [, x, =, x, -o, x, =, x, ], que [iria entender como comparar xcom xe xcom xe retornar verdadeiro.

Se $1fosse "* *", o shell passaria para o [comando a lista de arquivos no diretório atual cujo nome começa com x(a expansão global de x*), a lista de arquivos não ocultos (expansão *) ... que [é improvável que seja possível para fazer algum sentido. Os únicos casos em que isso faria algo sensato é se $1não contiver caracteres curinga ou caracteres em branco.

Agora, o que você encontra às vezes é um código como:

[ "x$1" = x ]

Isso é usado para testar se $1está vazio ou não definido.

A maneira normal de testar uma variável vazia ou não configurada é:

[ -z "$1" ]

Mas isso falha em alguns valores $1como =em algumas [implementações (não POSIX), como a incorporada no shell Bourne, como encontrada /bin/shno Solaris 10 e em versões anteriores ou anteriores de dash(até 0.5.4) ou shde alguns BSDs.

Isso porque [[, -z, =, ]e reclama sobre a falta de argumentos para o =operador binário em vez de compreendê-lo como o -zoperador unário aplicado à =string.

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

Naqueles shell / [implementações:

[ "x$1" = x ]

é sempre um teste válido, independentemente do valor de $1, também são:

[ "" = "$1" ]

e:

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

e

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

Obviamente, se você quiser verificar se nenhum argumento é fornecido, faça:

[ "$#" -eq 0 ]

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

Note-se que hoje em dia, [ -z "$var" ]é claramente especificado pelo POSIX e não pode falhar em conformant [implementações (e bash's [é e tem sido há décadas). Portanto, você deve poder confiar nele no sh POSIX ou nos bashscripts.

Stéphane Chazelas
fonte
0

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

harish.venkat
fonte
2
No x$1não é citado, portanto, a divisão e o globbing são executados nesses.
Stéphane Chazelas
0

[ x$1 = x ]é verdadeiro se $1nã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"

xx4h
fonte
1
[ x$1 = x ]também é verdade se, $1por exemplo " -o x". Tente sh -xc '[ x$1 = x ] && echo yes' sh ' -o x'. [ x$1 = x ]está errado e não faz sentido.
Stéphane Chazelas