O nome da variável do shell pode incluir um hífen ou traço (-)?

38

Eu não sou capaz de usar -em variáveis ​​no shell. Existe uma maneira de poder usá-lo, porque eu tenho um script que depende dessas variáveis ​​nomeadas:

$export a-b=c
-bash: export: `a-b=c': not a valid identifier

$export a_b=c

Primeiro lança o erro fornecido e o segundo funciona bem.

xyz
fonte
possível duplicado cross site de: stackoverflow.com/questions/2821043/...
Ciro Santilli新疆改造中心法轮功六四事件
Os shells geralmente não permitem nomes de variáveis. Você precisaria ignorar o shell, talvez até com um programa C personalizado carregando as variáveis ​​no ambiente do seu comando. Você não pode consertar esse erro de recurso (mesmo possível risco de segurança)?
vonbrand 19/07

Respostas:

47

Eu nunca conheci um shell no estilo Bourne que permitia -um nome de variável. Apenas letras ASCII (dos dois casos) _e dígitos são suportados, e o primeiro caractere não deve ser um dígito.

Se você possui um programa que requer uma variável de ambiente que não corresponde às restrições do shell, inicie-o com o envprograma.

env 'strange-name=some value' myprogram

Observe que alguns shells (por exemplo , traço moderno , mksh, zsh) removem variáveis ​​cujo nome não gostam do ambiente. (O Shellshock fez com que as pessoas fossem mais cautelosas em relação aos nomes de variáveis ​​de ambiente; portanto, é provável que as restrições se tornem mais rígidas ao longo do tempo, não mais permissivas.) Portanto, se você precisar passar uma variável cujo nome contenha caracteres especiais para um programa, passe-a diretamente, sem uma concha no meio ( env 'strange-name=some value' sh -c'…; myprogram'pode ou não funcionar).

Gilles 'SO- parar de ser mau'
fonte
Não funciona mais.
Jesse Glick
4
@JesseGlick Sim, sim. (O seu comentário seria útil se você definiu “não está funcionando”: com quais dados o que é o efeito em vez do efeito desejado e se você disse que a implementação de? envVocê usou sobre o sistema operacional.)
estar parada SO Gilles' evil '
Desculpe. O Ubuntu Yakkety com todas as atualizações, envfrom coreutils, shfrom dash: env 'with-dashes=value' bash -c 'env | fgrep dashes'funciona, mas env 'with-dashes=value' sh -c 'env | fgrep dashes'não imprime nada. Ou seja, envele é bom, mas o Dash parece bloquear especificamente essas variáveis. Portanto, se o programa em questão for iniciado por meio de um invólucro de shell com um #!/bin/shcabeçalho típico , não há uma maneira aparente de passar essas variáveis. solução alternativa de exemplo
Jesse Glick 14/04
@JesseGlick That's dash removendo a variável. Você deve usar envmais perto do site de chamada do programa que precisa desse nome de variável, sem um shell no meio. Dash não está sozinho na remoção de variáveis ​​cujo nome não gosta.
Gilles 'SO- stop being evil'
1
@JesseGlick É verdade que algumas coisas que costumava trabalhar pode não funcionam mais, porém: desde shellshock , as pessoas tornaram-se mais conservadora sobre nomes de variáveis, e traço de fato a mudança desde que eu escrevi esta resposta (e não como uma consequência de Shellshock, porém, mas para evitar um erro na mesma linha). Eu adicionei uma nota à minha resposta.
Gilles 'SO- stop be evil'
15

Isso não é possível no Bash.

Na seção Definições na página de manual de bash:

nome Uma palavra que consiste apenas em caracteres alfanuméricos e sublinhados e começa com um caractere alfabético ou um sublinhado. Também chamado de identificador.

De seção Parâmetros na página de manual de bash:

Um parâmetro é uma entidade que armazena valores. Pode ser um nome, um número ou um dos caracteres especiais listados abaixo em Parâmetros especiais. Uma variável é um parâmetro indicado por um nome.

Lekensteyn
fonte
2
+1 para demonstrar a utilidade das páginas de manual mais uma vez
ktf 31/10/11
2
Post antigo que eu conheço, mas quero ressaltar que para os iniciantes as páginas de manual podem ser bastante enigmáticas. Ainda tenho momentos em que preciso caçar melhores explicações / exemplos. Alguém estaria mentindo se dissessem que isso nunca aconteceu com eles.
TCZ8
1
@ TCZ8 As únicas pessoas que me disseram que achavam que as páginas de manual eram 'enigmáticas' são o mesmo tipo de pessoas que não lêem mensagens de erro e apenas lêem tudo, pulando o que precisam ler.
Route de milhas
13

Você pode acessar uma variável hifenizada usando uma referência indireta.

$ env 'my-hyphenated-variable=hello' /bin/bash
$ name='my-hyphenated-variable'
$ echo ${!name}
hello
Jon Nalley
fonte
1
Eu nunca tinha ouvido falar dessa funcionalidade até ler este comentário. Forneceu uma solução muito mais fácil para mim do que a resposta aceita.
precisa saber é o seguinte
7
Esse comportamento foi desabilitado nas versões mais recentes do bash. Consulte stackoverflow.com/questions/36989263/… para uma análise completa da situação.
Nicolas Dudebout
6

Se o seu script depende de nomes de variáveis ​​com hífens, isso é um erro de programação. Se for conveniente para você, devido às ferramentas que você usa regularmente para que os nomes das variáveis ​​contenham um hífen, talvez seja necessário aprender mais e diferentes ferramentas.

Você já tentou usar tr para converter os hífens em sublinhados?

hyphenated_name="a-b"
unhyphenated_name=$(echo $hyphenated_name | tr '-' '_')
declare -x $unhyphenated_name="some value"

O Bash permite que '-' apareça nos nomes das funções. Eu faço isso toda hora. Por exemplo:

function foo-bar() {
   echo "$@"
}
Brian J. Fox
fonte
2

O -caractere dash ( ) é um caractere de interrupção e não é permitido como parte dos nomes de variáveis. Existem maneiras de hackear isso com variáveis ​​citadas, mas a análise é realmente problemática. Também existem outros caracteres com significados especiais no contexto de nomes de variáveis ​​no bash, principalmente chaves, parênteses, caracteres do operador e aspas. (por exemplo, {}()=+-&'"e mais)

Eu sugeriria que praticamente você precisa encontrar outro paradigma para construir seu script. Você pode ter uma idéia de outras línguas sobre "nomes de variáveis ​​variáveis". Isso geralmente não é uma boa ideia nos scripts de shell.

Se você editar isso ou fizer uma nova pergunta com detalhes de seu contexto e o que você está tentando realizar, podemos sugerir uma boa maneira de criar um script.

Caleb
fonte
2

O manual do Bash define um "nome" como:

Uma 'palavra' consistindo apenas de letras, números e sublinhados e começando com uma letra ou sublinhado. Os nomes são usados ​​como variáveis ​​de shell e nomes de funções. Também chamado de 'identificador'.

Portanto, você não pode usar um hífen em um nome.

Michael Hoffman
fonte
0

A maioria dos shells suporta apenas az, AZ, 0-9 e _ para nomes de variáveis. Leia o segundo item nesta página .


fonte
0

Você pode jogar com env e sed.

Como exemplo, eu precisava ler esta variável 'ELASTICSEARCH_CLUSTER-NODES'.
O comando env produz este:

~ $ env
ELASTICSEARCH_CLUSTER-NODES=elasticsearch:9200
JAVA_ALPINE_VERSION=8.212.04-r0
HOSTNAME=17eb9e7fec4c
...

Então, para extrair a variável:

ESHOST=`env | sed -n 's/ELASTICSEARCH_CLUSTER-NODES=\(.*\)/\1/p'`
Guillaume Paramelle
fonte
-1

Acredito que apenas letras, números e sublinhado são permitidos para variáveis ​​bash. Este é o caso em muitas linguagens de programação (o javascript é uma exceção).

Eu recomendo que seu script não dependa desses tipos de nomes de variáveis.

Na verdade, você deve tentar programar de forma que possa substituir nomes de variáveis ​​por outros nomes e isso não faz diferença. Em geral, os nomes de variáveis ​​devem descrever o que a variável contém. Isso facilita muito a depuração; se não for para você, então para o próximo desenvolvedor que está tentando descobrir o código.


fonte
-1

Você pode usar o envcomando para definir e desmarcar variáveis ​​de ambiente com os hífens "-".

Para definir você deve usar env para executar o seu comando: env command. Você passa variáveis ​​desta maneira:

env a-b=c command

Veja trabalhando com:

env a-b=c env

ou para esclarecer:

env a-b=c env|grep 'a-b'
Neves
fonte