Uso prático da opção `set -k` no bash

16

Quando usamos a set -kopção no bash?

O manual de referência do Bash diz:

Todos os argumentos na forma de instruções de atribuição são colocados no ambiente para um comando, não apenas aqueles que precedem o nome do comando.

Entendo o que a opção faz, mas não conseguia imaginar quando precisamos dela.

MS.Kim
fonte
Percepção correta. O -kque nos permite executar scripts shell 30 anos de idade, sem a necessidade de refazer-los. Passar variáveis de ambiente temporários usando a sintaxe de prefixo em vez disso:var1=x var2=y command ...
Henk Langeveld

Respostas:

14

Você pode basicamente usá-lo sempre que quiser "injetar" as variáveis ​​de ambiente passadas para um script de shell (como argumentos) como se elas fossem definidas no ambiente via export, mas sem ter que residir permanentemente na exportlista antes de executar comandos .

NOTA: Também existe a forma longa do -kcomutador set -o keyword,.

Exemplo

$ cat cmd1.bash 
#!/bin/bash

echo $VARCMD

Agora se eu set -k:

$ set -k; ./cmd1.bash VARCMD="hi"; set +k
hi

Mas se eu fosse executar o script acima:

$ ./cmd1.bash 

$

O que a exportação está fazendo?

$ help export
...
Marks each NAME for automatic export to the environment of subsequently
executed commands.  If VALUE is supplied, assign VALUE before exporting.
...

Portanto, se adicionarmos export | grep VARao nosso script da seguinte forma:

$ cat cmd2.bash 
#!/bin/bash

echo $VARCMD
export | grep VAR

E executamos nossos testes acima novamente:

$ set -k; ./cmd2.bash VARCMD="hi"; set +k
hi
declare -x VARCMD="hi"

Mas sem set -k:

$ ./cmd2.bash 

$

O set -kque nos permite exportar temporariamente variáveis ​​em massa.

Outro exemplo

$ cat cmd3.bash 
#!/bin/bash

echo $VARCMD1
echo $VARCMD2
export | grep VAR

Quando definimos várias variáveis, todas são exportadas:

$ set -k; ./cmd3.bash VARCMD1="hi" VARCMD2="bye"; set +k
hi
bye
declare -x VARCMD1="hi"
declare -x VARCMD2="bye"

Então é só injetar todas as variáveis ​​de ambiente?

Não, -kestá fazendo uma coisa muito explícita aqui. É apenas exportar variáveis ​​que foram incluídas na linha de comando quando um comando foi executado.

Exemplo

Digamos que eu defina esta variável:

$ VARCMD1="hi"

Agora, quando executamos o mesmo comando, omitindo VARCMD1="hi":

$  set -k; ./cmd3.bash VARCMD2="bye"; set +k

bye
declare -x VARCMD2="bye"

Mas por que isso existe?

Encontrei esta fonte que explica um pouco sobre esse recurso, intitulado: "Keyword Parameter Assignment Strings". NOTA: O URL de origem usa um endereço IP, então não posso ligar para ele diretamente aqui na SE.

http://140.120.7.21/OpenSystem2/SoftwareTools/node16.html

Ao programar em qualquer idioma, a variável e sua passagem de valor são essenciais para escrever código confiável. Além dos tipos de variáveis ​​de número inteiro e matriz, todas as outras variáveis ​​de shell aceitam cadeias como seus valores. Ao falar sobre a linguagem de programação shell, para ser consistente, preferimos a frase "parâmetro da palavra-chave". Aqui estão alguns pontos a serem observados ao atribuir valores aos parâmetros da palavra-chave:

  • Para evitar qualquer efeito inesperado, sempre coloque a substring de atribuição de parâmetros na frente de uma sequência de comandos.

    No shell B, os valores atribuídos aos parâmetros da palavra-chave serão armazenados em variáveis ​​do shell (local). No bash e no ksh, as cadeias de caracteres de atribuição de parâmetro de palavra-chave que precedem o comando não serão armazenadas nas variáveis ​​do shell. Eles afetam apenas o subprocesso imediato bifurcado para executar o comando atual. Somente uma linha de cadeias de caracteres de atribuição de parâmetros de palavras-chave é armazenada nas variáveis ​​de shell (locais). As strings de atribuição de parâmetro de palavra-chave também podem aparecer como argumentos para os comandos alias, declare, typeset, export, readonly e builtin local. [Seção 3.4 do Manual de Referência do Bash]

  • As cadeias de atribuição de parâmetro de palavra-chave serão tratadas como argumentos para que o comando seja executado, se forem colocados após o nome do comando.

  • Os parâmetros da palavra-chave podem ser manipulados pelo comando set.
slm
fonte
Neste link, ss64.com/bash/set.html , pois set -keles deram -o keywordalém da -kopção. Isso significa alguma coisa?
Ramesh
@Ramesh - set -o keywordé a forma longa de set -k. Veja help set | grep -- '-k'.
slm
Ah ok. Eu estava coçando a cabeça por um longo tempo tentando entender por que existem duas opções. Como resposta perfeita habitual :)
Ramesh
4
./cmd.bash VARCMD=hiprecisa set -kfazê-lo funcionar exatamente como VARCMD=hi ./cmd.bashfaz sem o set -k. Adivinha pergunta específica do OP é em torno da necessidade de bash para apoiar o ./cmd.bash VARCMD=hiformulário
Iruvar
@ 1_CR - bom argumento. Eu acredito que tem a ver com estilo mais do que qualquer coisa, vou ver se consigo encontrar uma fonte real.
slm
8

Qualquer uso prático set -kprovavelmente é apenas estilo pessoal. Alguns - talvez aqueles que gostam de linguagens de programação que oferecem a capacidade de usar argumentos de palavras-chave em chamadas de função ou aquelas poucas pessoas que gostam ddda sintaxe do comando - possam preferir

set -k
...
comando var 1 = val 1 var 2 = val 2

para

comando
 var 1 = val 1 var 2 = val 2

A razão real pela qual a opção existe em alguns shells é explicada na lógica do comando set no padrão POSIX :

The following set flags were omitted intentionally with the following rationale:

The -k flag was originally added by the author of the Bourne shell to make it easier
for users of pre-release versions of the shell. In early versions of the Bourne shell
the construct
    set name=value
had to be used to assign values to shell variables.
Mark Plotnick
fonte