Diferença entre expansão e substituição na terminologia de script de shell

8

Expansão e Substituição parecem ser intercambiáveis no mesmo contexto na linguagem de programação shell. Por exemplo, alguns documentos, como o Manual de referência do Bash , Wiki do Bash Hackers use a palavra 'expansão' para explicar 'expansão do parâmetro do shell '. No entanto, alguns outros documentos parecem preferir a palavra "substituição". O Guia Avançado de Roteiro de Bash usa o parâmetro substituion . p>

Existe alguma diferença entre 'expansão' e 'substituição' em termos de terminologia de programação de shell?

    
por MS.Kim 16.04.2014 / 08:16

2 respostas

6

A substituição é quase sinónimo de expansão neste contexto porque os seus significados se sobrepõem. Nem uma subcategoria completa da outra, embora no Manual GNU seção que você faz referência há substituições que são consideradas como parte de uma expansão global.

Uma expansão está extraindo o valor de um identificador. Por exemplo, se this=that , quando expandirmos this , obteremos that . Uma expansão que não envolva substituição é pré-determinada em que o valor usado já existe e deve ser simplesmente recuperado, embora isso inclua a combinação de valores recuperados / explícitos (como "expansão aritmética").

Uma substituição cria um valor como resultado de uma operação explícita de entrada / saída. Por exemplo, se this=$(foo bar) , this é o resultado da execução de foo bar e da captura de sua saída. 1 Embora o valor resultante de uma substituição seja completamente previsível, é diferente do valor encontrado em uma expansão normal, porque na verdade não existe até a substituição ocorrer - é produzido.

As substituições vêm em dois tipos, comando e processo , que são simétricas:

# Command substitution
foo=$(ls)
# Process substitution
wc <(ls)

O "comando" no primeiro é ls , assim como o "processo" no segundo. Podemos dizer que o que está sendo substituído é realmente o fim de um cano. A substituição do processo se sobrepõe ao redirecionamento . No entanto, isso é provavelmente um pouco restritivo tecnicamente, o que nos leva à nota de rodapé ...

  1. foo bar , neste caso, poderia ser uma função de shell interna, caso em que não há E / S de interprocesso. A existência de built-ins shell menos obviamente obscurece essa diferença. Em termos de conteúdo, a entrada e a saída serão as mesmas.
por 16.04.2014 / 10:47
2
set -- arg arg2
echo ${2+"$1"}
 #OUTPUT 
arg

shift
echo ${2+"$1"}
 #OUTPUT

 #there doesn't seem to be anything here

Eu acho que a diferença é geralmente mínima para ser digna de nota - e os termos são frequentemente usados de forma intercambiável. No entanto, se você observar os dois casos acima, verá que no primeiro exemplo nós substituímos $1 por $2 como resultado da expansão de% código%. Assim que $2 não puder ser expandido , não haverá substituição.

Goldenilocks faz um bom ponto sobre a existência etérea de substituições. Mais ou menos como o gato de Schrodinger, eu acho. Isso me lembrou de algo. Você pode não estar familiarizado com essa forma de expansão de parâmetro especificada pelo POSIX, mas funciona de uma maneira oposta à forma acima:

${var:?if $var is unset or null its \
     parent shell dies and this message is output to stderr}

Agora, às vezes, quero o mesmo comportamento, mas para um valor $2 . O POSIX não especifica esse comportamento para nada exatamente. Mas, com um truque ou dois, é simplesmente gerenciado:

N= #N is null
var="any value should fail"
${var:+${N:?we substitute our \$Null var when \$var is expanded}}
  #OUTPUT
sh: line 3: N: we substitute our $Null var when $var is expanded

Mas:

N= #N is null
var=
${var:+${N:?is never substituted}}
  #OUTPUT

#there doesn't seem to be anything here
    
por 16.04.2014 / 09:01