将导出命令传递给 shell 脚本中的函数

Duc*_*ack 3 shell function

#!/bin/sh

execute_cmd()
{
   $($@)
}

execute_cmd export MY_VAR=my_val
echo ${MY_VAR}
Run Code Online (Sandbox Code Playgroud)

由于$()在子 shell 中执行,$MY_VAR因此在脚本运行的 shell 中没有正确设置。

我的问题是,如何将导出命令传递给函数并在运行脚本的当前 shell 中执行它?

Gil*_*il' 5

不清楚你想做什么。$($@)没有意义,但你想做什么?

有什么$($@)作用:

  • 取函数的参数。这是一个字符串列表。
  • 将每个部分进一步拆分,其中包含空格¹。
  • 取每个分割片并将其解释为通配符模式。如果模式匹配任何文件,则用匹配文件名列表替换该文件。
  • 使用第一部分作为要执行的命令(函数、shell 内置或可执行文件)的名称,并将其他部分作为参数传递。
  • 获取命令的输出并将其拆分为包含空格的位置。
  • 取每个分割片并将其解释为通配符模式。如果模式匹配任何文件,则用匹配文件名列表替换该文件。
  • 使用第一部分作为要执行的命令(函数、shell 内置或可执行文件)的名称,并将其他部分作为参数传递。

如果这听起来很复杂,那是因为它是。

如果你想execute_cmd export MY_VAR=my_val执行export MY_VAR=my_val,你为什么还要费心execute_cmd呢?

有两种方式可以明智地解释这一点。

  1. 您想将带参数的命令传递给函数。带参数的命令是一个字符串列表,第一个是函数名、shell 内置文件或可执行文件。那么在提供的参数上调用这个命令的语法是"$@".

    execute_cmd () {
      "$@"
    }
    execute_cmd export MY_VAR=my_val
    
    Run Code Online (Sandbox Code Playgroud)

    双引号避免了我上面提到的拆分和通配符扩展步骤。始终在变量替换周围使用双引号

    还要注意export关键字/内置的双重性质。虽然由于存在关键字而在 shell 解析export MY_VAR=$(seq 10)时分配seq 10to的输出,但 shell 不会解析为 in 的赋值,因为命令不在此处,但是,因此它被解析为任何参数的任何参数正常命令,并在 上执行 split+glob ,因此您需要:.$MY_VARMY_VAR=$(seq 10)exportMY_VAR=$(seq 10)execute_cmd export MY_VAR=$(seq 10)exportexecute_cmdMY_VAR=$(seq 10)$(seq 10)execute_cmd export MY_VAR="$(seq 10)"

  2. 你想运行一个 shell 片段。shell 片段是单个字符串,作为单个参数传递。要运行包含 shell 代码的字符串,请使用eval内置函数。

    execute_cmd () {
      eval "$1"
    }
    execute_cmd 'export MY_VAR=my_val'
    
    Run Code Online (Sandbox Code Playgroud)

¹假设默认IFS. 如果您知道这一点,则无需阅读本段。