@slm já incluiu os documentos POSIX - que são muito úteis - mas eles não expandem realmente como esses parâmetros podem ser combinados para afetar um ao outro. Ainda não há menção aqui desta forma:
${var?if unset parent shell dies and this message is output to stderr}
Este é um extrato de outra resposta da minha, e acho que demonstra muito bem como estes funcionam:
sh <<-\CMD
_input_fn() { set -- "$@" #redundant
echo ${*?WHERES MY DATA?}
#echo is not necessary though
shift #sure hope we have more than $1 parameter
: ${*?WHERES MY DATA?} #: do nothing, gracefully
}
_input_fn heres some stuff
_input_fn one #here
# shell dies - third try doesnt run
_input_fn you there?
# END
CMD
heres some stuff
one
sh: line :5 *: WHERES MY DATA?
Outro exemplo de mesmo :
sh <<-\CMD
N= #N is NULL
_test=$N #_test is also NULL and
v="something you would rather do without"
( #this subshell dies
echo "v is ${v+set}: and its value is ${v:+not NULL}"
echo "So this ${_test:-"\$_test:="} will equal ${_test:="$v"}"
${_test:+${N:?so you test for it with a little nesting}}
echo "sure wish we could do some other things"
)
( #this subshell does some other things
unset v #to ensure it is definitely unset
echo "But here v is ${v-unset}: ${v:+you certainly wont see this}"
echo "So this ${_test:-"\$_test:="} will equal NULL ${_test:="$v"}"
${_test:+${N:?is never substituted}}
echo "so now we can do some other things"
)
#and even though we set _test and unset v in the subshell
echo "_test is still ${_test:-"NULL"} and ${v:+"v is still $v"}"
# END
CMD
v is set: and its value is not NULL
So this $_test:= will equal something you would rather do without
sh: line 7: N: so you test for it with a little nesting
But here v is unset:
So this $_test:= will equal NULL
so now we can do some other things
_test is still NULL and v is still something you would rather do without
O exemplo acima aproveita todas as 4 formas de substituição do parâmetro POSIX e seus vários testes :colon null
ou not null
. Há mais informações no link acima e aqui está novamente .
Outra coisa que as pessoas geralmente não consideram sobre ${parameter:+expansion}
é o quão útil pode ser em um documento aqui. Veja outro trecho de uma resposta diferente :
TOP
Aqui você pode definir alguns padrões e se preparar para imprimi-los quando chamado ...
#!/bin/sh
_top_of_script_pr() (
IFS="$nl" ; set -f #only split at newlines and don't expand paths
printf %s\n ${strings}
) 3<<-TEMPLATES
${nl=
}
${PLACE:="your mother's house"}
${EVENT:="the unspeakable."}
${ACTION:="heroin"}
${RESULT:="succeed."}
${strings:="
I went to ${PLACE} and saw ${EVENT}
If you do ${ACTION} you will ${RESULT}
"}
#END
TEMPLATES
MÉDIO
Aqui é onde você define outras funções para chamar sua função de impressão com base em seus resultados ...
EVENT="Disney on Ice."
_more_important_function() { #...some logic...
[ $((1+one)) -ne 2 ] && ACTION="remedial mathematics"
_top_of_script_pr
}
_less_important_function() { #...more logic...
one=2
: "${ACTION:="calligraphy"}"
_top_of_script_pr
}
FUNDO
Você tem tudo configurado agora, então é aqui que você executará e extrairá seus resultados.
_less_important_function
: "${PLACE:="the cemetery"}"
_more_important_function
: "${RESULT:="regret it."}"
_less_important_function
RESULTADOS
Vou falar sobre o porquê daqui a pouco, mas a execução acima produz os seguintes resultados:
_less_important_function()'s
first run:
I went to your mother's house and saw Disney on Ice.
If you do calligraphy you will succeed.
então _more_important_function():
I went to the cemetery and saw Disney on Ice.
If you do remedial mathematics you will succeed.
_less_important_function()
novamente:
I went to the cemetery and saw Disney on Ice.
If you do remedial mathematics you will regret it.
COMO FUNCIONA:
A principal característica aqui é o conceito de conditional ${parameter} expansion.
Você pode definir uma variável para um valor somente se ela não estiver definida ou nula usando o formulário:
${var_name
:=desired_value}
Se, em vez disso, você quiser definir apenas uma variável não definida, omita o :colon
e os valores nulos permanecerão como estão.
ON SCOPE:
Você pode notar que no exemplo acima $PLACE
e $RESULT
são alterados quando definidos via parameter expansion
embora < em> _top_of_script_pr()
já foi chamado, presumivelmente definindo-os quando é executado. A razão pela qual isso funciona é que _top_of_script_pr()
é uma função ( subshelled )
- coloquei em parens
em vez de { curly braces }
usado para os outros. Como ele é chamado em um subshell, cada variável que ele configura é locally scoped
e, quando retorna ao shell pai, esses valores desaparecem.
Mas quando _more_important_function()
define $ACTION
, é globally scoped
, portanto, afeta _less_important_function()'s
segunda avaliação de $ACTION
porque _less_important_function()
define $ACTION
somente por ${parameter:=expansion}.