回显环境变量会返回字符串文字而不是环境变量值

时间:2017-03-02 18:54:53

标签: bash environment-variables echo fifo

我有两个bash脚本。第一个监听管道“myfifo”进行输入,并将输入作为命令执行:

fifo_name="myfifo"

[ -p $fifo_name ] || mkfifo $fifo_name;

while true
do
  if read line; then
    $line
  fi
done <"$fifo_name"

第二个命令'echo $ SET_VAR'传递给“myfifo”管道:

command='echo $SET_VAR'
command_to_pass="echo $command"
$command_to_pass > myfifo

如您所见,我想通过管道传递'echo $ SET_VAR'。在侦听器进程中,我设置了一个$ SET_VAR环境变量。我希望命令'echo $ SET_VAR'的输出为'var_value',它是环境变量SET_VAR的值。

在一个bash进程中运行第一个(侦听器)脚本,然后在另一个进程中通过第二个传递命令,会得到以下结果:

$SET_VAR

我希望打印“var_value”。而是打印字符串文字$ SET_VAR。为什么会这样?

2 个答案:

答案 0 :(得分:3)

在我遇到你报告的问题之前,我必须指出你的循环不起作用。 while true部分(循环中没有break)将永远运行。它将从文件读取第一行,循环,尝试读取第二行(失败),再次循环,尝试读取第三行(也失败),再次循环,尝试读取第四行等。 ..一旦read命令失败,您希望循环退出,因此请使用:

while read line
do
    # something I'll get to
done <"$fifo_name"

你遇到的另一个问题是shell扩展了变量(即将$var替换为变量var的值)中途解析a的过程命令行,当它完成时它不会返回并重新执行早期的解析步骤。特别是,如果变量的值包含$SET_VAR之类的内容,则它不会返回并扩展它,因为它刚刚完成扩展变量的位。实际上,它对扩展值的唯一作用是将其拆分为“单词”(基于空格),并展开它找到的任何文件名通配符 - 不会发生变量扩展,没有引用或转义解释等。

一种可能的解决方案是使用eval命令告诉shell运行解析过程两次

while read line
do
    eval "$line"
done <"$fifo_name"

(请注意,我在"$line"周围使用了双引号 - 这可以防止我提到的单词拆分和通配符扩展在 eval经过正常解析过程之前发生如果你认为你的原始代码在$line中半解析命令,没有双引号就会得到一个半解析的,这很奇怪。双引号抑制了一半-parsing stage,因此变量的内容只需解析一次。)

然而,这个解决方案带有一个很大的警告,因为eval作为一个臭虫磁铁享有当之无愧的声誉。 eval可以很容易地完成复杂的事情而不必了解正在发生的事情,这意味着您倾向于获得在测试中运行良好的脚本,然后在以后无法理解。根据我的经验,当eval看起来是最好的解决方案时,它可能意味着你正试图解决错误的问题。

那么,你究竟想做什么?如果您只是尝试执行来自fifo的行作为shell命令,那么您可以使用bash "$fifo_name"在子shell中运行它们,或source "$fifo_name"在当前shell中运行它们。

BTW,提供fifo的脚本:

command='echo $SET_VAR'
command_to_pass="echo $command"
$command_to_pass > myfifo

也是一场等待发生的灾难。将命令放在变量中并不能很好地在shell中工作(我的第二个chepner建议BashFAQ #50: I'm trying to put a command in a variable, but the complex cases always fail!),并且在变量中输入命令来打印另一个命令只是在乞求麻烦。

答案 1 :(得分:1)

bash,本质上,从stdin读取命令。你可以简单地运行:

bash < myfifo