【问题标题】:Listing all variables in a file in bash在bash中列出文件中的所有变量
【发布时间】:2016-02-02 23:26:09
【问题描述】:

在编写 bash 脚本时,我喜欢编写自包含函数,这些函数接受一个参数并基于该/那些参数执行操作,而不是在代码中的多个不同位置声明全局变量,从而降低可读性。

当您有一个需要使用多个变量的函数时,就会出现问题。将 10 个变量之类的东西传递给一个函数实在是太丑陋了,为此可以使用一个简单的关联数组。

如果我们想在外部文件中声明这些变量,“source”命令允许您将它们全部导入。

然后问题就变成了,我如何列出仅在此文件中声明的变量,以便我可以使用它们构建关联数组? 我已经能够使用“compgen”和循环的组合从变量列表中构建关联数组,但是如何只列出文件中找到的变量,无论它们被称为什么,所以我可以循环他们并建立我的阵列?

【问题讨论】:

  • 我倾向于建议为您的文档使用易于解析的注释格式(就像 doxygen、javadoc 和衍生工具一样)。
  • 您总是可以比较declare/set 在获取配置文件之前和之后的输出吗? =) 或者,如果配置文件对于该函数是唯一的,则直接创建数组。如果它不是函数独有的,那么您需要某种方法来只使用正确的变量,所以只需编写一个“collect_args”函数,该函数采用函数期望的变量名称等。
  • 谢谢。 @EtanReisner 我认为您的建议可能不得不这样做,因为除了解析实际文件之外,我似乎找不到更好的解决方案
  • 您实际上可能想查看github.com/threatgrid/declarative.bash。它可能对你有用。 (我对此一无所知,我只是将它放在标签中一段时间​​,然后回去查看。)
  • 您介意回复答案吗?您是否需要进一步的帮助,或者它可能不符合您的需求?

标签: bash shell associative-array compgen


【解决方案1】:

这是使用 awk 的一种方式:

egrep "*=" file |awk 'BEGIN{FS="="}{print $1}'|grep -v "#"|column -t

解释:

由于变量将具有“=”来分配值,因此将其用作模式 grep 文件中的“*=”。完成后,我将使用 awk 将字段分隔符声明为“=”并使用 $1 在它之前打印出任何内容。列 -t 仅用于将输出左对齐。

希望对你有帮助。

【讨论】:

  • grep -v "#" 用于省略注释变量。如果您还希望打印出注释的变量,则可以忽略这一点
【解决方案2】:

直接从文件中获取变量怎么样?

VARLIST=$(cut -d= -f1 file_with_variables)

【讨论】:

    【解决方案3】:

    你可以对你的文件中的一些变量声明语法做一个 egrep,然后通过剪切它来获取变量名,例如这样:

    egrep '[a-zA-Z0-9"'\''\[\]]*=' /path/to/file |egrep -v '^#' |cut -d'=' -f1 |awk '{print $1}'
    

    如果你有一个包含这样内容的文件

    #!/bin/bash
    
    A="test"
    
    somerandomfunction () {
            echo "test function"
            B="test"
    }
    
    #C="test"
    
    DEF="test"
    GHI1="test"
    JKL[1]="test"
    JKL['a']="test"
    JKL["b"]="test"
    

    上述命令的输出如下所示:

    A
    B
    DEF
    GHI1
    JKL[1]
    JKL['a']
    JKL["b"]
    

    命令说明:

    1. 第一个 egrep 搜索包含小写 (a-z) 和/或大写 (A-Z) 字母和/或方括号的任意数字和组合的行(\[\]) 和/或单引号 ('\'') 和/或双引号 (") 后跟 =
    2. 第二个 egrep 排除以 # 开头的行,因为这些行通常被解释为 cmets,不会生成或设置变量。
    3. cut 命令会删除从= 到行尾的所有内容。
    4. awk 命令会打印除空格或制表符之外的第一次出现的内容,因此可以有效地切掉变量名前面的空白空间。

    命令的输出可以用在循环中或类似的东西中:

    for VAR in $(egrep '[a-zA-Z0-9"'\''\[\]]*=' /path/to/file |egrep -v '^#' |cut -d'=' -f1 |awk '{print $1}'); do
      eval echo "\$${VAR}"
    done
    

    【讨论】:

    • 我通常只使用大写字母和数字作为变量名,以保持我的代码可读性。 :)
    • 谢谢。我会尽快调查此事。
    猜你喜欢
    • 1970-01-01
    • 2019-12-02
    • 2012-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-18
    相关资源
    最近更新 更多