如何创建bash环境变量,在命令前添加环境变量前缀?

时间:2020-05-19 18:32:35

标签: bash environment-variables

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

$ 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
$

...类似于无envvar前缀的方式,$FOO与在外壳上键入echo的效果相同。


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

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

更新

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

1 个答案:

答案 0 :(得分:5)

最好将数据放入变量,将代码放入函数。与保存代码的变量相比,函数更自然,更具表现力,更灵活。它们看起来与其他任何命令一样,但是可以采取任意操作,包括但不限于前置命令和变量分配。

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. 行情删除。此遍历在变量扩展后发生,但是 not 不适用于任何先前扩展步骤的结果。因此,删除了用户键入的引号,但保留了替换结果引号。

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