Define a variável para expandir a string vazia explícita?

3

Eu tenho um script de shell ( example ) da seguinte forma (simplificado):

#!/bin/sh
./somecommand -s ${DOMAIN_SUFFIX:=.example.com}

Se eu o executar como ./example , ele executará corretamente ./somecommand -s .example.com .

Se eu o executar como DOMAIN_SUFFIX=.stackexchange.com ./example , ele executará corretamente ./somecommand -s .stackexchange.com .

Pergunta: como eu defino DOMAIN_SUFFIX de forma que ela seja passada (dentro do script) como uma string vazia explícita?

Ou seja: eu preciso que ele execute ./somecommand -s '' .

Eu tentei DOMAIN_SUFFIX='' ./example , mas isso é executado em ./somecommand -s , o que falha.

    
por Roger Lipscombe 20.02.2017 / 17:44

4 respostas

1

Observe que, após todas as expansões terem sido realizadas pelo shell, e acabarem em um campo vazio, elas serão descartadas, a menos que tenham sido citadas. Como você não citou a variável, se ela for '' vazia '', ela deve ser descartada da lista de argumentos 'somecommands'. Não só isso, se DOMAIN_SUFFIX tiver espaços em branco ou widlcards, então você potencialmente surpreenderá o 'somecommand'.

Além disso, o $ {DOMAIN_SUFFIX: =. example.com} é um erro de digitação baseado nos resultados que você mostra para: DOMAIN_SUFFIX='' ./example , pois um DOMAIN_SUFFIX vazio seria substituído por seu valor padrão e, em seguida, colocado nos argumentos do somecommand Lista. Por isso, nunca vê um "vazio". ${DOMAIN=.example.com} explicará os resultados que você está obtendo.

    
por 20.02.2017 / 22:49
1

Uso:

"$ {DOMAIN_SUFFIX = .example.com}"

${parameter=default}, ${parameter:=default}

If parameter not set, set it to default.

Both forms nearly equivalent. The : makes a difference only when $parameter has been declared and is null.

link

Note que você também precisa de aspas "" para evitar que o valor vazio seja descartado, após a interpolação (acabou de notar que seu código estava faltando, obrigado @Gilles!).

Observe também que = (ou := ) também atribuirá o valor padrão a DOMAIN_SUFFIX (se não definido), portanto, se você precisar apenas obter o valor, convém usar - .

    
por 20.02.2017 / 17:57
0

TL, DR: Por que meu script de shell sufoca em espaços em branco ou outros caracteres especiais? . Ops, isso é ainda mais ... Bem, TL, DR reais: sempre coloque aspas duplas em torno das substituições de comando e variável. Além disso, veja o final desta resposta para um segundo problema com o seu script.

É impossível, com seu script, fazer uma expansão de variável se expandir para uma string vazia. Uma expansão de variável sem aspas passa pelo processo “expand + split + glob”:

  1. Pegue o valor da variável, que é uma string.
  2. Divida a string no espaço em branco (mais geralmente, nos caracteres que estão presentes no valor da variável IFS ). Isso resulta em uma lista de strings (possivelmente vazia se a string original continha nada além de espaço em branco).
  3. Para cada elemento da lista, se ele contiver pelo menos um caractere curinga *?\[ e o elemento for um padrão que corresponda a pelo menos um arquivo, o elemento será substituído pela lista de correspondências.

É possível que $DOMAIN_SUFFIX seja expandido para uma lista vazia de strings, mas não para uma lista que contenha uma string vazia. A etapa de correspondência de caractere curinga não pode produzir elementos vazios, pois um nome de arquivo nunca é a cadeia vazia. A etapa de divisão não pode produzir elementos vazios com o valor padrão de IFS , já que o separador é uma sequência de espaços em branco e leva pelo menos um caractere que não é espaço em branco para interromper uma sequência de espaços em branco. A etapa de divisão pode produzir elementos vazios se IFS for alterado para incluir caracteres que não sejam espaços em branco, mas isso exigiria a alteração do script para modificar IFS e não há motivos para isso.

Você precisa alterar o script e fazer com que ele use uma expansão simples de variável, em vez de usar o operador expandir + dividir + glob: coloque aspas duplas na expansão da variável.

Além disso, ${DOMAIN_SUFFIX:=.example.com} se expande para .example.com se o valor de DOMAIN_SUFFIX estiver vazio. Então você nunca terá uma string vazia para isso. Para preservar o valor vazio e usar somente .example.com se DOMAIN_SUFFIX não estiver definido, altere o := para = .

#!/bin/sh
./somecommand -s "${DOMAIN_SUFFIX=.example.com}"
    
por 21.02.2017 / 02:08
0

Acho que esta é a parte do manual bash que você está procurando (POSIX tem uma redação semelhante do mesmo efeito :

When not performing substring expansion, using the forms documented below (e.g., :-), bash tests for a parameter that is unset or null. Omitting the colon results in a test only for a parameter that is unset.

A diferença entre uma variável não definida e uma variável com um valor nulo é que uma variável não definida ainda não existe.

Então,

#!/bin/bash

bash -c 'echo "$#"; printf "%s\n" "$@"' -- "${DOMAIN_SUFFIX=.example.com}"

Isso definirá DOMAIN_SUFFIX para .example.com se DOMAIN_SUFFIX não estiver definido, mas não se for nulo (uma string vazia).

O comando usado aqui simplesmente gerará um novo processo bash que imprimirá o número do argumento da linha de comando passado, seguido por todos os parâmetros posicionais, um em cada linha:

bash-4.4$ bash script
1
.example.com
bash-4.4$ DOMAIN_SUFFIX=.hello.world bash script
1
.hello.world
bash-4.4$ DOMAIN_SUFFIX= bash script
1

bash-4.4$

No último exemplo, DOMAIN_SUFFIX= é idêntico a DOMAIN_SUFFIX='' .

    
por 20.02.2017 / 21:17

Tags