shell变量名称可以包含连字符或连字符(-)吗?


38

我无法-在shell中的变量中使用。有没有一种方法可以使用它,因为我有一个脚本依赖于这样的命名变量:

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

$export a_b=c

第一个抛出给定的错误,第二个工作正常。



Shell通常不允许使用此类变量名。您可能不得不绕过外壳程序,即使使用自定义C程序将变量加载到命令环境中也是如此。您不能解决此功能失调(甚至可能导致安全隐患)吗?
vonbrand

Answers:


47

我从未见过允许-使用变量名的Bourne风格的shell 。仅支持ASCII字母(无论哪种情况)_和数字,并且第一个字符不能为数字。

如果您的程序需要的环境变量与shell限制不匹配,请与该env程序一起启动它。

env 'strange-name=some value' myprogram

请注意,某些外壳程序(例如,现代dash,mksh,zsh)会从环境中删除其名称不喜欢的变量。(Shellshock使人们对环境变量名称更加谨慎,因此限制可能会随着时间的流逝而变得更加严格,而不是更加宽松。)因此,如果您需要将名称中包含特殊字符的变量传递给程序,请直接将其传递,中间没有外壳(env 'strange-name=some value' sh -c'…; myprogram'可能会也可能不会工作)。


不再有效。
Jesse Glick

4
@JesseGlick是的。(如果您定义“不起作用”:用什么数据?是什么效果而不是预期的效果?并且如果您说env在哪种操作系统上使用了哪种实现,您的评论将非常有用。)
Gilles'SO-邪恶的

抱歉。带有envfrom coreutilsshfrom dash:的所有更新的Ubuntu Yakkety可以env 'with-dashes=value' bash -c 'env | fgrep dashes'工作,但不env 'with-dashes=value' sh -c 'env | fgrep dashes'打印任何内容。也就是说,env它本身很好,但是Dash似乎专门阻止了这些变量。因此,如果所讨论的程序是通过具有典型#!/bin/sh头文件的外壳包装程序启动的,则没有明显的方法来传递此类变量。解决方法示例
Jesse Glick

@JesseGlick这有点破除变量。您必须在env需要此变量名的程序的调用站点附近使用,而在两者之间没有外壳。Dash并不是唯一一个删除其名称不喜欢的变量的方法。
吉尔斯(Gilles)'所以

1
@JesseGlick确实,某些曾经起作用的东西可能不再起作用了:自shellshock以来,人们对变量名变得更加保守,而自从我写了这个答案以来,破折号实际上发生了变化(尽管不是Shellshock的结果,但要避免出现相同的错误)。我在回答中添加了注释。
吉尔斯(Gilles)'所以

15

在Bash中是不可能的。

在以下手册页的“ 定义”部分中bash

名称仅由字母数字字符和下划线组成的单词,以字母字符或下划线开头。也称为标识符。

在以下手册页的“ 参数”部分中bash

参数是存储值的实体。它可以是名称,数字或特殊参数下面列出的特殊字符之一。变量是用名称表示的参数。


2
+1再次展示了手册页的有用性
ktf,

2
我知道旧帖子,但是,我想指出,对于新手来说,手册页可能是非常神秘的。我仍然有很多时候需要寻找更好的解释/示例。如果他们说从来没有发生过,那么任何人都会撒谎。
TCZ8 2014年

1
@ TCZ8唯一告诉我他们认为手册页是“隐秘的”的人就是那种不阅读错误消息而只是略读所有内容的人,直接跳过了他们需要阅读的内容。
Miles Rout


6

如果您的脚本依赖于变量名带有连字符,那就是编程错误。如果由于经常使用使变量名包含连字符的工具而对您方便,则可能需要学习更多不同的工具。

您是否尝试过使用tr将连字符转换为下划线?

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

Bash允许'-'出现在函数名称中。我一直都这样做。例如:

function foo-bar() {
   echo "$@"
}

2

破折号(-)字符是换行符,不允许作为变量名的一部分。有很多方法可以用带引号的变量来破解它,但是解析它确实是有问题的。在bash中的变量名称的上下文中,还有其他具有特殊含义的字符,特别是花括号,括号,运算符和引号。(例如{}()=+-&'"更多)

我建议实际上,您需要找到另一种构建脚本的范例。您可能对其他语言有关于“变量变量名称”的想法。在shell脚本中,这通常不是一个好主意。

如果您对此进行编辑或提出一个有关您的上下文以及要完成的任务的详细信息的新问题,我们可能会建议一种编写脚本的好方法。


2

Bash手册将“名称”定义为:

仅由字母,数字和下划线组成的“单词”,以字母或下划线开头。“名称”用作外壳程序变量和函数名称。也称为“标识符”。

因此,您不能在名称中使用连字符。


0

大多数外壳程序仅支持将az,AZ,0-9和_作为变量名。阅读此页面的第二项。


0

您可以玩env和sed。

例如,我需要读取此变量“ ELASTICSEARCH_CLUSTER-NODES”。
env命令输出以下内容:

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

因此要提取变量:

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

-1

我相信bash变量仅允许使用字母,数字和下划线。在许多编程语言中都是这种情况(javascript是一个例外)。

我建议您不要让脚本取决于变量名称的那些类型。

实际上,您应该尝试以可以将变量名替换为其他名称的方式进行编程,并且这没有什么区别。通常,变量名称应描述变量包含的内容。这使得调试变得更加容易。如果不适合您,则为下一个试图找出代码的开发人员。


-1

您可以使用该env命令来设置和取消设置带有“-”的环境变量。

要进行设置,您必须使用env运行命令:env command。您可以通过以下方式传递变量:

env a-b=c command

看到它与:

env a-b=c env

或使其更清楚:

env a-b=c env|grep 'a-b'
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.