Como evitar a divisão de palavras sem impedir a remoção da string vazia?

6

Eu preciso passar como argumento de programa uma expansão de parâmetro. A expansão resulta em um nome de arquivo com espaços. Portanto, cito duas vezes para ter o nome do arquivo como uma única palavra: "$var" .

Contanto que $var contenha um nome de arquivo, o programa recebe um argumento de palavra única e funciona bem. No entanto, às vezes, a expansão resulta em uma sequência vazia, que, quando passada como argumento, quebra o programa (que não posso alterar).

Não remover a string vazia é o comportamento especificado, de acordo com o Bash Reference Manual:

If a parameter with no value is expanded within double quotes, a null argument results and is retained.

Mas então, como gerencio o caso em que preciso citar variáveis, mas também preciso descartar uma expansão de string vazia?

EDITAR:

Graças a George Vasiliou, vejo que um detalhe está faltando na minha pergunta (tentei resumir :)). A execução do programa é uma longa chamada java, que é abreviada assim:

java -cp /etc/etc MyClass param1 param2 "$var" param4

De fato, usar uma instrução if como a descrita por George resolveria o problema. Mas isso exigiria uma chamada com "$ var" na cláusula then e outra sem "$ var" na cláusula else .

Para evitar a repetição, eu queria ver se existe uma maneira de usar uma única chamada que descarta a expansão de "$ var" quando está vazia.

    
por ARX 29.12.2016 / 15:23

3 respostas

7

O formulário ${parameter:+word} expansão do parâmetro parece fazer o trabalho

( xyz=2; set -- ${xyz:+"$xyz"}; echo $# )
1

( xyz=; set -- ${xyz:+"$xyz"}; echo $# )
0

( unset xyz; set -- ${xyz:+"$xyz"}; echo $# )
0

Então, isso deve ser traduzido para

program ${var:+"$var"}

no seu caso

    
por 29.12.2016 / 15:49
4

Em bash e shells com suporte a matriz semelhante, você pode fazer o seguinte:

# default is an empty array
param=()

# if $var is not empty then add it to array
[[ "$var" ]] && param=("$var")

# use the $@-like magic for arrays
java -cp /etc/etc MyClass param1 param2 "${param[@]}" param4

Demo

demo() {
  [[ "$var" ]] && param=("$var") || param=()

  echo -n 'output: '
  printf '<%s> ' before "${param[@]}" after
  echo
}

demo # output: <before> <after> 

var=''
demo # output: <before> <after> 

var='foo bar'
demo # output: <before> <foo bar> <after> 

Nota

Veja também link onde a abordagem da resposta do iruvar é também explicado novamente.

    
por 29.12.2016 / 16:08
3

Não está claro o que você está tentando fazer, mas não é um simples, se o suficiente? Por exemplo:

[[ ! -z "$var" ]] && call_program_with_arg "$var" 

Ou

if [[ ! -z "$var" ]];then call_program "$var";fi

Se $ var estiver vazio, nada acontece. Se não estiver vazio, chame o programa desejado.

Após a atualização das perguntas:

parameters=( "Param1" "Param2" )
[[ ! -z "$var" ]] && parameters+=( "$var" "Param4") || parameters+=( "Param4" )
java -cp /etc/etc MyClass "${parameters[@]}"

Teste:

$parameters=( "Param1" "Param2" );var="my file.java";[[ ! -z "$var" ]] && parameters+=( "$var" "Param4") || parameters+=( "Param4" );echo java -cp /etc/etc MyClass "${parameters[@]}"                                                                                                              
>java -cp /etc/etc MyClass Param1 Param2 my file.java Param4
$parameters=( "Param1" "Param2" );var="";[[ ! -z "$var" ]] && parameters+=( "$var" "Param4") || parameters+=( "Param4" );echo java -cp /etc/etc MyClass "${parameters[@]}"                                                                                                               
>java -cp /etc/etc MyClass Param1 Param2 Param4 
    
por 29.12.2016 / 15:36