A sintaxe "$ {PS1-}" é válida e como ela difere da simples "$ PS1"?

12

Eu estou olhando para um script que possui:

if [ "${PS1-}" ]; then

Essa trilha -me incomoda um pouco, porque não parece com a sintaxe padrão Posix ou Bash. É alguma sintaxe misteriosa que existe desde sempre, ou é um erro de digitação? Qualquer referência a padrões / documentos seria apreciada.

Normalmente eu codificaria:

if [ "$PS1" ]; then

O que é mais correto ou há uma diferença entre eles?

Gregor
fonte

Respostas:

12

Essa é definitivamente a sintaxe do POSIX . Parafraseando:

Usando ${parameter-word}, se parameterfor

  • definido e não nulo, substitua o valor de parameter,
  • definido mas nulo, substitua nulo e
  • desabilitar e substituir word.

Sessão de exemplo:

$ echo "${parameter-word}"
word
$ parameter=
$ echo "${parameter-word}"

$ parameter=value
$ echo "${parameter-word}"
value

"Nulo" aqui significa simplesmente a string vazia. Não há valor nulo especial nos shells POSIX, em contraste com o SQL, por exemplo.

Isso também está documentado na seção "Expansão de parâmetros" de man bash.

l0b0
fonte
1
Eu acho que as páginas de manual bash e dash estão incompletas, porque elas não mencionam essa sintaxe (ímpar)!
Gregor
1
@ Gregor Ambos os manuais mencionam isso. No manual do Bash, ele está no parágrafo anterior à lista de expansões de parâmetros, e no manual do Dash, no parágrafo seguinte.
Kusalananda
1
OK, "Omitindo o cólon ...." Eu não vi isso :(
Gregor
zshé o único shell que conheço que menciona explicitamente as variantes sem cólon, em vez de apenas tomar nota do que omitir o cólon faz.
Chepner
1
@pts, o texto no POSIX praticamente usa exclusivamente o termo "nulo", o que pode explicar seu uso nas páginas de manual.
Ilkkachu
23

A expansão da variável ${parameter:-word}usará o valor de $parameterse estiver definido e não for nulo (não uma sequência vazia), caso contrário, a sequência será usada word.

A omissão do :teste não testará se o valor está vazio, apenas se está desconfigurado ou não.

Isso significa que ${PS1-}será expandido para o valor de $PS1se estiver definido, mas para uma sequência vazia se estiver vazia ou não definida. Neste caso, este é exatamente o mesmo como ${PS1:-}como a cadeia depois -também está vazio.

A diferença entre "${PS1-}"e "$PS1"é sutil, como observa @Rakesh Sharma: ambos serão expandidos para o valor de $PS1ou para uma string vazia, se não estiver definida. A exceção é quando set -uestá ativo; nesse caso, a expansão de variáveis ​​não definidas causaria um erro . O valor padrão (vazio) definido por "${PS1-}"contorna isso, expandindo um conjunto PS1para a sequência vazia sem erro.

Essa é a sintaxe padrão ( originada no shell Bourne no final dos anos 70 ), assim como outras expansões semelhantes.

Kusalananda
fonte
E desde que foi citado, é o mesmo que "$PS1", se if PS1está vazio, está vazio, e as aspas evitam que a palavra desapareça completamente.
Ilkkachu
4
Contanto que o set -unão esteja em vigor. Quando a opção de conjunto de substantivos está ativada, "$ PS1" => gera erro. "$ {PS-}" não.
@RakeshSharma esse é um bom ponto. A sintaxe diferente pode realmente gerar resultados diferentes, dependendo da opção do conjunto de substantivos; portanto, o teste ["$ {parameter-}"] provavelmente está mais correto!
Gregor
1
@ Kusalananda: Observe que ${parameter:-word}o valor será usado $parameterse NÃO for NULL. Em todos os outros casos (ou seja: definido, mas NULL ou não definido), ele será usado word. Sua formulação:if its set or null
@ikkachu: Sim, está correto. Somente quando as variáveis ​​forem set AND nonnull=> use-se. Caso contrário, ( set but NULL OR unset) => use word.
6

A sintaxe:

${parameter:-word}

e um formulário especial:

${parameter-word}

é a sintaxe válida no shell do POSIX , significa usar o valor padrão wordse parameterfor definido ou nulo.


Normalmente, com wordestá vazio, então:

${parameter-}

e:

$parameter

ou:

${parameter}

são equivalentes.

Porém, sob o efeito de set -u, todas as variáveis ​​não definidas fazem com que o shell seja encerrado. ${parameter-}é usado para ignorar essa regra estrita. Funciona nos dois casos, então sim, é a maneira mais correta.

cuonglm
fonte