如何在命令之前创建一个环境变量前缀的 bash 环境变量?

Sto*_*row 2 bash environment-variables

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

$ cat ./src
FOO="echo"
$ . ./src
$ echo $FOO
echo
$ $FOO hello
hello
$
Run Code Online (Sandbox Code Playgroud)

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

$ 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
$
Run Code Online (Sandbox Code Playgroud)

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

$ MY_DIR=/tmp echo hello
hello
$
Run Code Online (Sandbox Code Playgroud)

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


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

$ ls -ld /tmp/
drwxrwxrwt. 25 root root 500 May 19 11:35 /tmp/
$
Run Code Online (Sandbox Code Playgroud)

更新:

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

Joh*_*ica 5

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

foo() {
    MY_DIR=/tmp echo "$@"
}
Run Code Online (Sandbox Code Playgroud)
foo hello
Run Code Online (Sandbox Code Playgroud)

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

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

恐怕这种限制是不可能的。

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

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

如果您想了解具体细节,请打开Bash 手册页。它非常长,细节分散在各处。让我拉出关键部分和一些精选引文来帮助您消化它:

  1. Shell 语法,简单命令

    一个简单的命令是一系列可选的变量赋值,后跟以空格分隔的单词和重定向,并以控制运算符结束。

  2. 简单的命令扩展

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

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

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

    ...

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

  3. 扩张

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

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

  4. 扩展、参数扩展

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

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

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

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

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

  3. 报价删除。变扩建后该通票情况,但要注意,它适用于任何先前的扩张步骤的结果。所以用户输入的引号被删除,但作为替换结果的引号被保留。

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