Bash:遍历变量名 [英] Bash: Iterate over variable names

查看:58
本文介绍了Bash:遍历变量名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个bash脚本来分析一些文件.在第一次迭代中,我为每个要分析的类别创建具有单词计数的关联数组.这些类别不是预先知道的,因此这些关联数组的名称是可变的,但所有前缀都具有相同的 count_ $ category .关联数组将一个单词作为关键字,并将其在该类别中的出现次数计为值.

I'm writing a bash script to analyse some files. In a first iteration I create associative arrays with word counts for each category that is analysed. These categories are not known in advance so the names of these associative arrays are variable but all with the same prefix count_$category. The associative arrays have a word as key and its occurrence count in that category as value.

分析完所有文件后,我必须总结每个类别的结果.我可以使用 $ {count _ *} 遍历变量名,但是如何访问这些变量名后面的关联数组?对于每个关联数组(每个 count _ * 变量),我应该遍历单词及其计数.

After all files are analysed, I have to summarise the results for each category. I can iterate over the variable names using ${count_*} but how can I access the associative arrays behind those variable names? For each associative array (each count_* variable) I should iterate over the words and their counts.

我已经尝试过这样的间接访问,但是它不起作用:

I have already tried with indirect access like this but it doesn't work:

for categorycount in ${count_*} # categorycount now holds the name of the associative array variable for each category
do
    array=${!categorycount}
    for word in ${!array[@]}
    do
        echo "$word occurred ${array[$word]} times"
    done
done

推荐答案

现代(bash 4.3+)方法使用"namevars",这是从ksh借来的工具:

The modern (bash 4.3+) approach uses "namevars", a facility borrowed from ksh:

for _count_var in "${!count_@}"; do
    declare -n count=$_count_var                  # make count an alias for $_count_var
    for key in "${!count[@]}"; do                 # iterate over keys, via same
        echo "$key occurred ${count[$key]} times" # extract value, likewise
    done
    unset -n count                                # clear that alias
done

declare -n count = $ count_var 允许"$ {count [foo]}" 用于在其中查找项目 foo 名为 count_var 的关联数组;同样, count [foo] = bar 将分配给同一项目. unset -n count 然后删除此映射.

declare -n count=$count_var allows "${count[foo]}" to be used to look up item foo in the associative array named count_var; similarly, count[foo]=bar will assign to that same item. unset -n count then removes this mapping.

bash 4.3之前的版本:

Prior to bash 4.3:

for _count_var in "${!count_@}"; do
  printf -v cmd '_count_keys=( "${!%q[@]}" )' "$_count_var" && eval "$cmd"
  for key in "${_count_keys[@]}"; do
    var="$_count_var[$key]"
    echo "$key occurred ${!var} times"
  done
done

请注意使用%q 而不是将变量名直接替换为字符串,来生成用于 eval 的命令.即使在这种情况下我们可能是安全的(因为可能的变量名的集合受到限制),但是按照这种做法可以减少确定间接扩展是否安全所需考虑的上下文量.

Note the use of %q, rather than substituting a variable name directly into a string, to generate the command to eval. Even though in this case we're probably safe (because the set of possible variable names is restricted), following this practice reduces the amount of context that needs to be considered to determine whether an indirect expansion is secure.

在两种情况下,请注意内部变量( _count_var _count_keys 等)使用的名称与 count _ * 模式不匹配

In both cases, note that internal variables (_count_var, _count_keys, etc) use names that don't match the count_* pattern.

这篇关于Bash:遍历变量名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆