3

问题:

我在 ruby​​ 脚本中将 shell 脚本作为子进程运行,在运行脚本后,我希望有一个选项来检查 shell 的所有环境变量,包括数组变量。

到目前为止,我想出了:

set | awk -F= 'BEGIN            {v=0;}
  /^[a-zA-Z_][a-zA-Z0-9_]*=/    {v=1;}
  v==1 && $2~/^['\''\$]/        {v=2;}
  v==1 && $2~/^\(/              {v=3;}
  v==2 && /'\''$/ && !/'\'\''$/ {v=1;}
  v==3 && /\)$/                 {v=1;}
  v                             {print;}
  v==1                          {v=0;}
'

这很好地只显示了变量,包括数组、多行字符串和过滤掉的函数。

但这并不总是使用相同的格式,尤其是数组变量在 BASH 和 ZSH 中的表示方式不同。

这是我当前的实现:https ://github.com/mpapis/tf/blob/master/lib/tf/environment.rb

问题:

有没有一种简单的方法来显示所有将在 BASH 和 ZSH / 可能其他 shell 中持续工作的变量。

4

2 回答 2

7

很高兴再次见到你 mpapis ;-)

不幸的是,POSIX.1-2008 没有涵盖数组和关联数组,并且您发现 和 之间存在一些令人讨厌的细微bash差别zsh。因此,没有单一的方法可以在所有 POSIX shell 中执行此操作,我们需要检查$BASH_VERSION等,正如您已经指出的那样。

我决定最好避免编写 Ruby 来解析set或其他shell内置函数的输出。输出不方便解析,而且无论如何 shell 最了解自己的数据,所以我认为将大部分智能放在 shell 代码中是有意义的。因此,我提出了一个解决方案,它使用 shell 代码将数据结构输出为YAML,然后将 YAML 直接加载到 Ruby 中。

首先,我将您的参考实现和测试导入到独立存储库master分支中。然后我加强了测试套件并进行了一些调整。这表明多行处理仍然存在问题。

然后我创建了一个新yaml分支并开发了自己的实现。我再次扩展了测试。他们都通过了 ;-) 请注意,我使用了一些不同的技巧在zshand中进行自省bash

  • zsh有一个zsh/parameter模块,它提供包含其所有参数的名称和类型的关联数组。
  • bash具有declare -p易于解析的形式。它也有compgen -A variable,但最后我没有使用它。

ksh我认为添加支持也很容易。

于 2012-08-18T19:18:16.780 回答
1

set返回所有shell变量,而不是环境变量。要获取环境变量,请使用env命令。请注意,bash 不会将数组导出到环境中。

于 2012-08-14T16:47:15.607 回答