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

将导出命令传递给 shell 脚本中的函数
#!/bin/sh

execute_cmd()
{
   $($@)
}

execute_cmd export MY_VAR=my_val
echo ${MY_VAR}

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

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

答案1

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

什么$($@)是:

  • 获取函数的参数。这是一个字符串列表。
  • 在包含空格的地方进一步分割每个部分。
  • 取出每个分割部分并将其解释为通配符模式。如果该模式与任何文件匹配,则用匹配文件名列表替换该部分。
  • 使用第一部分作为要执行的命令的名称(函数、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
    

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

    export还要注意关键字/内置的双重性质。虽然由于关键字的存在, shell 可以像解析那样将export MY_VAR=$(seq 10)的输出分配给,但是 shell 不会将其解析为 中的赋值,因为命令不在这里,但是,因此被解析为任何普通命令的任何参数,并且 split+glob 是在 上执行的,因此您需要:。seq 10$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'
    

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

答案2

你应该检查一下吉尔斯的回答了解所有详细信息。eval简而言之,您可以使用$()

execute_cmd()
{
    eval "$@"
}

bash手册

评估[参数]

这些参数连接在一起形成一个命令,然后读取并执行该命令,其退出状态作为 eval 的退出状态返回。如果没有参数或只有空参数,则返回状态为零。

其他外壳通常有eval 内置具有相似的语义。

相关内容