#!/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
?
有两种方法可以合理地解释这一点。
您想要将带有参数的命令传递给函数。带参数的命令是一个字符串列表,第一个是函数名称、shell 内置或可执行文件。那么对提供的参数调用此命令的语法是
"$@"
。execute_cmd () { "$@" } execute_cmd export MY_VAR=my_val
双引号避免了我上面提到的拆分和通配符扩展步骤。始终在变量替换周围使用双引号。
export
还要注意关键字/内置的双重性质。虽然由于关键字的存在, shell 可以像解析那样将export MY_VAR=$(seq 10)
的输出分配给,但是 shell 不会将其解析为 中的赋值,因为命令不在这里,但是,因此被解析为任何普通命令的任何参数,并且 split+glob 是在 上执行的,因此您需要:。seq 10
$MY_VAR
MY_VAR=$(seq 10)
export
MY_VAR=$(seq 10)
execute_cmd export MY_VAR=$(seq 10)
export
execute_cmd
MY_VAR=$(seq 10)
$(seq 10)
execute_cmd export MY_VAR="$(seq 10)"
您想要运行一个 shell 片段。 shell 片段是单个字符串,作为单个参数传递。要运行包含 shell 代码的字符串,请使用
eval
内置函数。execute_cmd () { eval "$1" } execute_cmd 'export MY_VAR=my_val'
1假设默认IFS
.如果您知道这一点,则无需阅读本段。