【问题标题】:How can I create a bash environment variable that prefixes an environment variable before a command?如何在命令之前创建一个在环境变量前面加上前缀的 bash 环境变量?
【发布时间】:2020-05-19 18:32:35
【问题描述】:

我似乎能够创建执行命令的环境变量;像这样:

$ cat ./src
FOO="echo"
$ . ./src
$ echo $FOO
echo
$ $FOO hello
hello
$

有没有办法可以修改该环境变量,以便它在命令之前添加 另一个环境变量的设置? 即有没有办法解决以下问题?

$ cat ./src
FOO="MY_DIR=/tmp echo"
$ . ./src
$ echo $FOO
MY_DIR=/tmp echo
$ $FOO hello
-bash: MY_DIR=/tmp: No such file or directory
$

即我想要做的是有一个环境变量,它相当于在 shell 中手动键入以下内容:

$ MY_DIR=/tmp echo hello
hello
$

...类似于 sans envvar-prefix, $FOO 与在 shell 中键入 echo 的效果相同。


/tmp/ 当然存在,顺便说一句:

$ ls -ld /tmp/
drwxrwxrwt. 25 root root 500 May 19 11:35 /tmp/
$

更新:

我有一个约束,即“FOO”必须像$FOO hello 而不是FOO hello 那样调用。所以不幸的是,像@John Kugelman 的(当前)答案这样的函数不能成为解决方案,即使它更合适。

【问题讨论】:

  • 回复:“我有一个约束,必须像 $FOO hello 而不是 FOO hello 那样调用 'FOO':如果这是字面上唯一的问题,那么别担心,那约束很容易适应:您可以只写FOO=FOO,然后$FOO hello 将扩展为FOO hello 并调用您可能定义的任何FOO 函数。
  • 设置是否必须是分配给FOO,您可以在调用FOO="MY_DIR=/tmp echo" 之前获得设置代码吗?像.bashrc 文件或类似文件?
  • @root - 事实证明,我认为你的建议是可以的;抱歉,如果这些是我应该提前提到的细节,但是 bash 编程的所有许多语义和扩展、设置等规则仍然经常超出我的直接掌握,所以我经常无法合理化与提及。

标签: bash environment-variables


【解决方案1】:

最好将数据放入变量,将代码放入函数。函数比保存代码的变量更自然、更富有表现力和更灵活。它们看起来就像任何其他命令,但可以执行任意操作,包括但不限于前置命令和变量赋值。

foo() {
    MY_DIR=/tmp echo "$@"
}
foo hello

这里"$@" 是传递给foo() 的参数的占位符。

我有一个约束,“FOO”必须像 $FOO hello 而不是 FOO hello 那样调用。

恐怕这种约束是不可能的。

我对这里发生的事情的机制很好奇:即为什么你可以创建一个对命令“别名”的环境变量(我知道真正的别名是另外一回事),但该机制不适应为命令添加前缀“stuff”看似很小的变化?

Bash 以固定的、规定的顺序在若干遍中扩展命令。很早就将命令拆分为单词,然后用不可见的标志标记变量分配。它会在稍后的通道中扩展 $variable 引用。它不会查看结果以查看它们是否看起来像额外的变量扩展。等号实际上被忽略了。

如果您想了解细节,请打开Bash man page。它非常长,细节分散在各处。让我把关键部分和一些选择引用来帮助你消化它:

  1. Shell 语法,简单命令

    简单命令是一系列可选变量赋值,后跟空白分隔的单词和重定向,并由控制操作符终止。

  2. 简单的命令扩展

    当执行一个简单的命令时,shell 会从左到右执行以下扩展、赋值和重定向。

    1. 解析器标记为变量赋值(命令名称前面的那些)和重定向的词被保存以供以后处理。

    2. 不是变量赋值或重定向的词被扩展。如果展开后还有单词,则将第一个单词作为命令名称,其余单词作为参数。

    ...

    如果没有得到命令名,变量赋值会影响当前的 shell 环境。否则,变量会被添加到执行命令的环境中,不会影响当前的shell环境。

  3. 扩展

    在被拆分成单词后在命令行上执行扩展。执行的扩展有七种:大括号扩展波浪号扩展参数和变量扩展命令替换算术扩展分词路径名扩展

    扩展的顺序是:大括号扩展、波浪号扩展、参数、变量和算术扩展和命令替换(以从左到右的方式完成)、分词和路径名扩展。

  4. 扩展、参数扩展

    $ 字符引入了参数扩展、命令替换或算术扩展。

在第 1 步中标记分配,在第 4 步中扩展变量(AKA 参数)。

变量扩展后发生的唯一事情是:

  1. 分词。如果变量包含空格,它可以扩展为多个单词。 (或者更准确地说,如果它包含字段间分隔符变量$IFS 中的任何字符。)

  2. 路径名扩展。 也称为通配符或通配符。如果变量包含*?[,它们将扩展为匹配文件的名称(如果有)。

  3. 引号删除。此过程发生在变量扩展之后,但它确实适用于任何先前扩展步骤的结果。因此,用户键入的引号被删除,但作为替换结果的引号被保留。

分词和路径名扩展都不是您需要的,这就是为什么不能将赋值存储在变量中的原因。

【讨论】:

    猜你喜欢
    • 2015-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-27
    • 2011-12-22
    • 2022-01-12
    相关资源
    最近更新 更多