【问题标题】:Examine Bash variables with dynamic names检查具有动态名称的 Bash 变量
【发布时间】:2017-09-04 12:51:36
【问题描述】:

我正在尝试从我知道名称后缀的 Bash 变量中读取,但我想遍历前缀。

下面我举个例子:

var1_name="variable1"
var1_size="2"
var2_name="variable2"
var2_size="3"
vars=(var1 var2)

for v in "${vars[@]}"
do
    echo $v_name
    echo $v_size
done

我希望输出如下所示:

variable1
2
variable2
3

有什么可以用 Bash 做到这一点吗? 我已尝试使用 eval 和关联数组,但我仍然找不到检查已定义变量的方法。

【问题讨论】:

    标签: bash variables eval associative-array variable-names


    【解决方案1】:

    以下对我有用。您需要先构造变量,然后使用感叹号对其进行评估。

    var1_name="variable1"
    var1_size="2"
    var2_name="variable2"
    var2_size="3"
    vars=("var1" "var2")
    
    for v in "${vars[@]}"
    do
        name=${v}_name
        size=${v}_size
        echo ${!name}
        echo ${!size}
    done
    

    O/P

    variable1
    2
    variable2
    3
    

    【讨论】:

      【解决方案2】:

      auhuman's helpful answer 完全按照您的要求解决了您的问题。

      这里有一个替代方案,它不需要您首先在数组中指定名称前缀,假设所有感兴趣的变量都具有相同前缀的名称,例如var: p>

      for name in "${!var@}"  # Loop over all variables whose names start with 'var'.
      do
          [[ $name =~ ^var[0-9]+_(name|size)$ ]] || continue # Ignore unrelated names.
          echo "${!name}" # Use variable indirection to print the variable's value. 
      done
      
      • 代码使用两种形式的 Bash 变量间接,均基于语法${!...}:

        • "${!var@}" 是基于 literallist 形式:它扩展为 list(数组)所有已定义变量的名称,其名称具有文字前缀var(其名称​​以var开头),如果有的话。由于只允许在 @ 之前使用文字,因此遗憾的是,使用
          "${!var[0-9]_@}" 等模式进行更复杂的匹配不起作用

          • 示例:for varName in "${!HOST@}"; do echo "$varName"; done
            例如,产生HOSTNAMEHOSTTYPE

          • 相关的${!var*} 语法(没有双引号)似乎工作相同。
            (奇怪的是,man 页面声称 $IFS 值的第一个字符用于连接匹配的名称,如果第一个字符是 whitespace 字符($IFS 默认值是这样,它以空格开头),但实际上始终使用 space,而不管 $IFS 的值如何; 验证(IFS=@; echo ${!HOST*}))

        • ${!name},基于​​变量标量形式,扩展为名称的变量的值> 存储为$name 的值。

          • 示例:var='value'; name='var'; echo ${!name} 产生 value

          • 注意:通过一个技巧(上面没有使用),您可以使用间接获取数组的值 ,即通过将所有索引表达式[@]附加到变量的名称以间接引用;例如:
            arr=( one two three ); name='arr[@]'; echo "${!name}" 产生one two three;以这种方式访问​​特定元素(例如,name='arr[1]')也可以,但是提取 范围 的元素不会(例如,name='arr[@]: 0:2')。

        • 还有一个 array-index list 形式 - not 在上面使用 - 扩展为列表(数组)给定数组/关联数组的索引/键。

          • 示例:arr=( one two three ); echo "${!arr[@]}"
            产生0 1 2,数组的隐式顺序索引。

          • 它与显式分配的索引(例如,
            arr=( [10]=one two three ); echo "${!arr[@]}")类似地工作,或者在 Bash v4+ 中,与关联数组一起工作(尽管,由于关联数组的性质,不保证键是按定义顺序列出;例如,
            declare -A aarr=( [one]=1 [two]=2 ); echo "${!aarr[@]}")。

      • [[ $v =~ ^var[0-9]+_(name|size)$ ]] 使用 =~ 运算符将手头的变量名称与 RHS 上的扩展正则表达式进行匹配,以确定它是否是感兴趣的名称。

      【讨论】:

      • 我实际上不使用名称 var1、var2... 这有点不同,但对于我在该脚本中所做的类似事情可能非常有用,谢谢!
      • @OfriRips:明白,谢谢。我已经更清楚地说明我的答案假定了一个共享名称前缀(并且我添加了变量间接的概述)。感谢您回来并接受 auhuman 的回答。还请考虑重新审视您的旧问题,看看那里的答案是否值得被接受。
      猜你喜欢
      • 2022-11-24
      • 1970-01-01
      • 1970-01-01
      • 2013-01-12
      • 2015-05-24
      • 2015-06-20
      • 2019-09-15
      • 1970-01-01
      • 2013-05-09
      相关资源
      最近更新 更多