Como posso testar se uma variável está vazia ou contém apenas espaços?

215

A seguinte sintaxe do bash verifica se param não está vazio:

 [[ !  -z  $param  ]]

Por exemplo:

param=""
[[ !  -z  $param  ]] && echo "I am not zero"

Nenhuma 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"

"Não sou zero" é emitido.

Como posso alterar o teste para considerar variáveis que contêm apenas caracteres de espaço como vazios?

    
por maihabunash 28.07.2014 / 11:16

7 respostas

262

Primeiro, observe que o -z test é explicitamente para:

the length of string is zero

Ou seja, uma string contendo apenas espaços deve não ser verdadeira em -z , porque tem um tamanho diferente de zero.

O que você deseja é remover os espaços da variável usando a substituição de padrão expansão de parâmetros :

[[ -z "${param// }" ]]

Isso expande a variável param e substitui todas as correspondências do padrão (um único espaço) por nada, portanto, uma string que tenha apenas espaços será expandida para uma string vazia.

O detalhes de como isso funciona é que ${var/pattern/string} substitui a primeira correspondência mais longa de pattern com string . Quando pattern começa com / (como acima), ele substitui all as correspondências. Como a substituição está vazia, podemos omitir o% final/ e o valor string :

${parameter/pattern/string}

The pattern is expanded to produce a pattern just as in filename expansion. Parameter is expanded and the longest match of pattern against its value is replaced with string. If pattern begins with ‘/’, all matches of pattern are replaced with string. Normally only the first match is replaced. ... If string is null, matches of pattern are deleted and the / following pattern may be omitted.

Depois de tudo isso, acabamos com ${param// } para excluir todos os espaços.

Observe que, embora presente em ksh (onde originou), zsh e bash , essa sintaxe não é POSIX e não deve ser usada em sh scripts.

    
por 28.07.2014 / 11:30
27

A maneira fácil de verificar se uma string contém apenas caracteres em um conjunto autorizado é testar a presença de caracteres não autorizados. Assim, em vez de testar se a cadeia contém apenas espaços, teste se a cadeia contém algum caractere diferente de espaço. No bash, ksh ou zsh:

if [[ $param = *[!\ ]* ]]; then
  echo "\$param contains characters other than space"
else
  echo "\$param consists of spaces only"
fi

"Consiste apenas em espaços" inclui o caso de uma variável vazia (ou não definida).

Você pode querer 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.

A correspondência de uma string com um padrão com = dentro de [[ … ]] é uma extensão ksh (também presente em bash e zsh). Em qualquer estilo Bourne / POSIX, você pode usar a construção case para corresponder uma string a um padrão. Observe que os padrões de shell padrão usam ! para negar um conjunto de caracteres, em vez de ^ como na maioria das sintaxes de expressões regulares.

case "$param" in
  *[!\ ]*) echo "\$param contains characters other than space";;
  *) echo "\$param consists of spaces only";;
esac

Para testar os caracteres de espaço em branco, a sintaxe $'…' é específica de ksh / bash / zsh; você pode inserir esses caracteres em seu script literalmente (observe que uma nova linha terá que estar entre aspas, como barra invertida + nova linha expande-se para nada) ou gerá-los, por exemplo,

whitespace=$(printf '\n\t ')
case "$param" in
  *[!$whitespace]*) echo "\$param contains non-whitespace characters";;
  *) echo "\$param consists of whitespace only";;
esac
    
por 29.07.2014 / 02:37
19

POSIXly:

case $var in
  (*[![:blank:]]*) echo '$var contains non blank';;
  (*) echo '$var contains only blanks or is empty or unset'
esac

Para diferenciar entre blank , não em branco , vazio , não configurado :

case ${var+x$var} in
  (x) echo empty;;
  ("") echo unset;;
  (x*[![:blank:]]*) echo non-blank;;
  (*) echo blank
esac

[:blank:] é para caracteres de espaçamento horizontal (espaço e tabulação em ASCII, mas provavelmente há mais alguns em sua localidade; alguns sistemas incluirão o espaço sem quebra (quando disponível), outros não). Se você quiser também caracteres de espaçamento vertical (como nova linha ou feed de formulário), substitua [:blank:] por [:space:] .

    
por 30.07.2014 / 09:25
4
if [[ -n "${variable_name/[ ]*\n/}" ]]
then
    #execute if the the variable is not empty and contains non space characters
else
    #execute if the variable is empty or contains only spaces
fi
    
por 15.09.2015 / 11:30
3

O único motivo restante para escrever um script de shell, em vez de um script em uma linguagem de script good , é se a portabilidade extrema é uma preocupação primordial. O legado /bin/sh é a única coisa que você pode ter certeza de que tem, 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 realmente universais - e tenha em mente 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 :

[ "x'printf '%s' "$var" | tr -d "$IFS"'" = x ]

(O valor padrão de $IFS , convenientemente, é um espaço, uma tabulação e uma nova linha.)

(O printf builtin é em si mesmo bastante portátil, mas confiar nele é muito menos complicado do que descobrir qual variante de echo você tem.)

    
por 28.07.2014 / 17:41
-1

Para testar se a variável está vazia ou contém espaços, você também pode usar este código:

${name:?variable is empty}
    
por 29.07.2014 / 12:58
-1

Tente isto:

$ [[ -z \'echo $n\' ]] && echo zero

zero
    
por 05.08.2016 / 12:49