【问题标题】:How to find variable names in Bash source code如何在 Bash 源代码中查找变量名
【发布时间】:2019-12-15 20:14:15
【问题描述】:

我正在编写一个允许本地函数命名空间的实验性 Bash 模块系统,我的第一个想法是编写一个 Bash 函数解析器,它将逐行读取函数代码并在每个函数/变量名称前加上 <module-name>. (即模块 module 中的函数 func 将变为 module.func - 可以再次导入到另一个模块中,如 module_2.module.func 等等;函数内部的变量将被命名 - 函数 @987654327 内的变量 var @ 模块中的 module 将变为 __module_func_var)。

但是,为了做到这一点,我需要一种方法来检测哪些名称是变量,并用传输的导入名称替换它们在函数中的所有出现。像variable=[...] 这样的琐碎案例很容易解析,但还有无数其他情况不是那么琐碎的——while read variable; do [...] donevariable2="asdf${variable//_/+}" 呢?

在我看来,为了做到这一点,我需要深入研究 Bash 的解析机制或阅读一本关于编程语言的书——但是为了实现我上面解释的内容,我该从哪里开始呢?

【问题讨论】:

    标签: bash parsing variables module namespaces


    【解决方案1】:

    我需要一种方法来检测哪些名称是变量

    我很抱歉这么说,但总的来说这是不可能的。

    仅支持可能出现变量的 static 情况是可能的,但非常棘手。只考虑变量赋值:除了x=,还有declare x=printf -v xread xmapfile xreadarray x,可能还有更多。即使像 shellcheck 这样的成熟工具在正确解析所有这些情况时仍然存在问题(例如,请参阅 this issue)。

    但是,即使你掌握了正确解析所有 static 的情况,仍然可以使用 dynamic 变量,例如:

    x=$(someCommand)
    declare "$x=something"
    

    在此示例中,如果不执行 someCommand,您将无法知道新变量的名称。其他同样(甚至更糟)的事情是bash 的间接运算符${!x}、算术上下文中的隐式间接(例如x=y; echo $((x)))和eval

    tl;dr: 获取脚本中所有变量的唯一方法是解释/执行脚本。

    但是还有另一个问题:如果存在不确定性 (declare "$(tr -cd a-z /dev/urandom | head -c1)=..."),执行脚本也不是一个选项。请注意,用户输入也是不确定的 (read x; declare "var$x=...")。您将不得不编写一个静态分析器。但由于停机问题,这也不是一种选择。从停止问题中,我们可以推断(通常)不可能判断给定的 bash 脚本是否具有有限数量的变量。


    要实现您的模块系统,您可以使用另一种方法。例如,如果有人想为您的框架实现一个模块,那么他们必须以易于解析的格式指定该模块中的函数/变量。

    【讨论】:

    • 是的,我认为这会很棘手。现在我想起来了,完全正确地进行这种解析需要解决停机问题——因为人们可以轻松地在 Bash 中编写图灵机并实现如下功能:if halts_on TM input; then declare "var$x=..."; else declare "car$x=...... 创建特殊语法不是我的原来的计划,因为没有人喜欢学习新的语法,并且解析器将成为脚本的依赖项。我有点希望它适合当前的 Bash 实现。
    猜你喜欢
    • 2011-12-10
    • 1970-01-01
    • 2020-10-07
    • 1970-01-01
    • 2011-03-04
    • 1970-01-01
    • 2016-06-12
    • 1970-01-01
    • 2018-03-11
    相关资源
    最近更新 更多