A seguinte sintaxe do bash verifica se param
não está vazia:
[[ ! -z $param ]]
Por exemplo:
param=""
[[ ! -z $param ]] && echo "I am not zero"
Sem saída e tudo bem.
Mas quando param
está vazio, exceto por um (ou mais) caracteres de espaço, o caso é diferente:
param=" " # one space
[[ ! -z $param ]] && echo "I am not zero"
"Eu não sou zero" é emitido.
Como posso alterar o teste para considerar variáveis que contêm apenas caracteres de espaço como vazias?
bash
shell
shell-script
string
maihabunash
fonte
fonte
man test
:-z STRING - the length of STRING is zero
. Se você deseja remover todos os espaços$param
, use${param// /}
trim()
função simples embutida em qualquer * nix? Tantos hacks diferentes para conseguir algo tão simples ...[[ ! -z $param ]]
é equivalente atest ! -z $param
.Respostas:
Primeiro, observe que o
-z
teste é explicitamente para:Ou seja, uma string contendo apenas espaços não deve ser verdadeira abaixo
-z
, porque tem um comprimento diferente de zero.O que você deseja é remover os espaços da variável usando a expansão do parâmetro de substituição de padrão :
Isso expande a
param
variável e substitui todas as correspondências do padrão(um único espaço) por nada; portanto, uma sequência que possui apenas espaços será expandida para uma sequência vazia.
O âmago da questão de como isso funciona é que
${var/pattern/string}
substitui a primeira partida mais longa depattern
comstring
. Quandopattern
começa com/
(como acima), substitui todas as correspondências. Como a substituição está vazia, podemos omitir o final/
e ostring
valor:Depois de tudo isso, acabamos
${param// }
excluindo todos os espaços.Observe que, embora esteja presente em
ksh
(onde ele se originou)zsh
ebash
, essa sintaxe não é POSIX e não deve ser usada emsh
scripts.fonte
sed
eles disseram ... apenasecho
a variável que eles disseram ... #${var/pattern/string}
assim, não deveria ser[[ -z ${param/ /} ]]
o espaço entre as barras para ser o padrão e nada depois para ser a corda?[[ -z "${param// }" ]]
certeza parecepattern
vazia e oreplacement string
espaço é único. Ah! Agora vejo queif pattern begins with a slash
perdi essa parte. então o padrão é/
e a string é deixada de lado e, portanto, vazia. Obrigado.A maneira mais fácil de verificar se uma string contém apenas caracteres em um conjunto autorizado é testar a presença de caracteres não autorizados. Portanto, em vez de testar se a cadeia contém apenas espaços, teste se a cadeia contém algum caractere que não seja o espaço. No bash, ksh ou zsh:
"Consiste apenas em espaços" inclui o caso de uma variável vazia (ou não definida).
Você pode testar qualquer caractere de espaço em branco. Use
[[ $param = *[^[:space:]]* ]]
para usar configurações de localidade ou qualquer lista explícita de caracteres de espaço em branco que você deseja testar, por exemplo,[[ $param = *[$' \t\n']* ]]
para testar espaço, tabulação ou nova linha.Combinar uma string com um padrão com
=
inside[[ … ]]
é uma extensão ksh (também presente no bash e no zsh). Em qualquer estilo Bourne / POSIX, você pode usar acase
construção para combinar uma sequência com um padrão. Observe que os padrões de shell padrão são usados!
para negar um conjunto de caracteres, e não^
como na maioria das sintaxes de expressão regular.Para testar caracteres em branco, a
$'…'
sintaxe é específica para ksh / bash / zsh; você pode inserir esses caracteres no seu script literalmente (observe que uma nova linha terá que estar entre aspas, pois a barra invertida + a nova linha se expandirá para nada) ou gerá-las, por exemplofonte
${var?not set}
- passar nesse teste e sobreviver garantiria que uma variável correspondida por você*)
case
efetuaria uma definição definitiva. resposta, por exemplo.[[ $param = *[!\ ]* ]]
entrarmksh
.POSIXly:
Para diferenciar entre em branco , não em branco , vazio e não definido :
[:blank:]
é para caracteres de espaçamento horizontal (espaço e tabulação em ASCII, mas provavelmente há mais alguns no seu código do idioma; alguns sistemas incluirão o espaço sem quebra (quando disponível), outros não). Se você quiser caracteres de espaçamento vertical também (como nova linha ou feed de formulário), substitua[:blank:]
por[:space:]
.fonte
zsh
parece ter problema com[![:blank:]]
, aumento:b
é modificador inválido. Insh
eksh
emular, evento de aumento não encontrado para[
var=foo zsh -c 'case ${var+x$var} in (x*[![:blank:]]*) echo x; esac'
está bem para mim. O evento não encontrado seria apenas para shells interativos.:b
modificador inválido é um pouco estranho.sh
ébash
construído com--enable-xpg-echo-default
e de--enable-strict-posix-default
modo a ser compatível com Unix (que envolve aecho '\t'
saída de uma guia).O único motivo restante para escrever um script de shell, em vez de um script em uma boa linguagem de script, é se a portabilidade extrema é uma preocupação primordial. O legado
/bin/sh
é a única coisa que você pode ter certeza, mas o Perl, por exemplo, tem mais probabilidade de estar disponível em várias plataformas do que o Bash. Portanto, nunca escreva scripts de shell que usem recursos que não sejam verdadeiramente universais - e lembre-se de que vários fornecedores proprietários de Unix congelaram seu ambiente de shell antes do POSIX.1-2001 .Existe uma maneira portátil de fazer esse teste, mas você precisa usar
tr
:(O valor padrão de
$IFS
, convenientemente, é um espaço, uma guia e uma nova linha.)(O
printf
próprio built-in é muito portátil, mas confiar nele é muito menos complicado do que descobrir qual a sua varianteecho
).fonte
case
.case
globo para detectar uma string que está vazia ou que contém apenas caracteres em branco. (Seria fácil com uma expressão regular, mascase
não faz regexps A construção em sua resposta não vai funcionar se você se preocupa com novas linhas..)case $param in *[![:space:]]*) …
. Se você deseja testar osIFS
caracteres, pode usar o padrão*[$IFS]*
.<space><tab><newline>
no início e nunca mais o toca. Eu pensei que seria uma distração..profile
que foram executados por muitas conchas Bourne. É claro[$IFS]
que não fará o que foi planejado seIFS
tiver certos valores não padrão (vazio (ou não definido), contendo]
, começando com!
ou^
).fonte
Para testar se a variável está vazia ou contém espaços, você também pode usar este código:
fonte
:
.name=aaaa
, em seguida, executar este comandoecho ${name:?variable is empty}
imprimirá valor do nome da variável e agora executar este comandoecho ${name1:?variable is empty}
ele irá imprimir SH: name1: variável está vaziaecho ${name:?variable is empty}
avaliará o$name
valor não nulo ou matará o shell. Portanto, pela mesma razão que você não fazprompt > $randomvar
nem deveria${var?}
- se houver um comando lá, provavelmente será executado - e você não sabe o que é. Um shell interativo não precisa sair - e é por isso que o seu não. Ainda assim, se você quiser ver alguns testes, existem muitos aqui. . Este não é tão longa ...Para testar se uma variável está desmarcada, vazia (tem um valor nulo) ou contém apenas espaços:
Explicação:
${param%%[! ]*}
remove do primeiro não espaço até o fim.-z
, faça ecoempty
.O acima é compatível com POSIX e é executado em qualquer descendente de Bourne.
Se você deseja estender isso para também as guias, inclua uma guia explícita:
ou use uma variável com os caracteres que você precisa remover:
ou você pode usar alguma "expressão de classe de caractere" POSIX (em branco significa espaço e guia):
Mas isso falhará em mksh, lksh e nobre.
fonte
Tente o seguinte:
fonte