如何在bash中嵌套变量并遍历子变量

时间:2018-08-16 08:04:14

标签: arrays bash shell loops

我正在尝试编写一个从mysql生成csv文件的脚本。来自mysql的csv文件运行正常,但是,我正在努力寻找一种循环遍历变量或将其视为要遍历的数组的方法。

一些示例变量在下面

c1="Client 1"
c1_s1_name=Alpha
c1_s1_id=761967
c1_s2_name=Beta
c1_s2_id=415612

c2="Client 2"
c2_s1_name=XYZ
c2_s1_id=438976
c2_s2_name=ABC
c2_s2_id=982012

c3="Client 3"
c3_s1_name=No-Name
c3_s1_id=347654
c3_s2_name=House
c3_s2_id=109321

然后我有一些准代码,试图为每个client如下运行sql脚本,但

# loop through all clients
for all_clients in $c1 $c2 $c3
do

# and then loop through for all survey names and all survey ids for each seperate client
for survey_name in $*_name and survey_id in $*_id
do
mysql -h "localhost" -u "root" "$DATABASE" -e "SELECT count(*) FROM $survey_id" | sed 's/\t/","/g;s/^/"/;s/$/"/;s/\n//g' > $all_clients-$survey_name-filename-count.csv
done

done

我不确定如何设置脚本,以使c1变量作为一组运行,然后依次运行c2c3。我猜可能需要一个数组,但不确定吗?

我也遇到了以下答案,但这是针对PHP的,即使它看起来像bash一样可疑...

Group variables and loop through them

1 个答案:

答案 0 :(得分:1)

您需要构建动态变量的名称,然后使用{!var}语法对其取消引用。假定您事先知道变量名(即,第一部分始终为c1c2c3,第二部分始终为s1s2 ,…),您可以使用类似这样的内容:

for x in c1 c2 c3; do
  for y in s1 s2; do
    for z in name id; do
      xyz=${x}_${y}_${z}
      # Use ${!xyz} to get the contents of the variable
    done
  done
done

Example(但是显然没有您的mysql调用)

我使用了xyz来强调变量的构造方式,但是 您可以将x替换为all_clients,等等。

如果事先不知道c*s*的数目,则可以使用稍微先进的技术。

numc=3
nums=2
for x in $(seq -f 'c%g' $numc); do
  for y in $(seq -f 's%g' $nums); do
    for z in name id; do
      xyz=${x}_${y}_${z}
      # Use ${!xyz} to get the contents of the variable
    done
  done
done

Example

这里的魔法来自seq。例如,在以下调用中:

seq -f 'c%g' $numc

$numc选项表明您要从1迭代到$numc-f 'c%g'选项表示您希望形成类似printf的字符串,在这种情况下,字母c后跟数字值。因此,上面的示例将写为:

c1
c2
c3

整个字符串由$()捕获,这意味着输出将内联到您的脚本中。总而言之,以下行:

for x in $(seq -f 'c%g' $numc); do

将被解释为:

for x in c1 c2 c3; do

与初始for循环等效,不同之处在于,现在您可以控制迭代次数。