在循环中创建带有大括号扩展的数组

在循环中创建带有大括号扩展的数组

我想生成一些仅按年份不同的数组。在循环中,我创建带有大括号扩展和变量的数组。

我尝试了以下代码但没有成功:

LIST={JF,JFE,RFS,JBF,JFI,JMCB}
for year in {1998..2000} {2009..2011}
do
  declare -a 'y$year=('"$LIST"'-$year)'
  echo "${y$year[@]}"
done

结果应该是以下条目的列表:

y1998: JF-1998 JFE-1998 RFS-1998 JBF-1998 JFI-1998 JMCB-1998
y1999: JF-1999 JFE-1999 RFS-1999 JBF-1999 JFI-1999 JMCB-1999
...
y2011: JF-2011 JFE-2011 RFS-2011 JBF-2011 JFI-2011 JMCB-2011

我不需要打印它们,只需在循环中使用它们并将它们作为参数传递即可。因为第二个,evalin-loop 是不够的。

答案1

推迟大括号扩展确实是一个例子eval,特别是如果你想对事物进行字符串化 -普通的参数扩展没有做正确的事情在正确的时间。

这应该做你想要的事情:

LIST={JF,JFE,RFS,JBF,JFI,JMCB}
for year in {1998..2000} {2009..2011}
do
  eval "y$year=($LIST-$year)"
  tmp="y$year[@]"
  echo "${!tmp}"
done

eval您不能间接访问数组,因此如果您想将其打印出来,则必须在太内对数组进行字符串化。如果不这样做,您可以取出之后的所有内容; tmp是用来间接扩张:如果tmp设置为"y$year[@]",其中$year被替换为其值,则扩展${!tmp}给出本次迭代数组的内容(${y1998[@]}等将扩展为什么)。

上面将输出:

JF-1998 JFE-1998 RFS-1998 JBF-1998 JFI-1998 JMCB-1998
JF-1999 JFE-1999 RFS-1999 JBF-1999 JFI-1999 JMCB-1999
JF-2000 JFE-2000 RFS-2000 JBF-2000 JFI-2000 JMCB-2000
JF-2009 JFE-2009 RFS-2009 JBF-2009 JFI-2009 JMCB-2009
JF-2010 JFE-2010 RFS-2010 JBF-2010 JFI-2010 JMCB-2010
JF-2011 JFE-2011 RFS-2011 JBF-2011 JFI-2011 JMCB-2011

并创建数组y1998....y2011这些declares 并不是绝对必要的,但eval如果您希望这样做并且不需要字符串化,它们确实可以让您跳过 an 。

我认为这可能不是你真正想要实现你的根本目标的方式,不管那是什么。嵌套循环并不是邪恶的,如果其中任何一点是硬编码的,您都可以将其抽象出来。

答案2

这是一种方法(带支撑扩展):

unset y _y
for y in {JF,JFE,RFS,JBF,JFI,JMCB,}-{{1998..2000},{2009..2011}}
do  case "${_y=y${y#*-}[@]}"               in 
    (y${y#-}*) echo "${!_y}"               ;; 
    (*)        declare -a "${_y%???}+=($y)";; 
esac; unset y _y; done

这会将循环的参数集扩展for到所有所需的值额外的最后一组仅包含年份。对于每一个这样做的不是以数字开头,declare将数组成员添加到y${y##*[!0-9]}出现的任何内容中,并且对于每个数字echo打印它。

因此,对于前 36 次迭代,它构建每个数组,对于后 6 次迭代,它打印每个数组。输出是:

JF-1998 JFE-1998 RFS-1998 JBF-1998 JFI-1998 JMCB-1998
JF-1999 JFE-1999 RFS-1999 JBF-1999 JFI-1999 JMCB-1999
JF-2000 JFE-2000 RFS-2000 JBF-2000 JFI-2000 JMCB-2000
JF-2009 JFE-2009 RFS-2009 JBF-2009 JFI-2009 JMCB-2009
JF-2010 JFE-2010 RFS-2010 JBF-2010 JFI-2010 JMCB-2010
JF-2011 JFE-2011 RFS-2011 JBF-2011 JFI-2011 JMCB-2011

这是一个替代方案,也许......

for year in 1998 1999 2000 2009 2010 2011
do  printf "%s-$year " JF JFE RFS JBF JFI JMCB
echo; done

这至少会让你得到相同的输出...也可以将其存储在数组中,也许你可以...

for year in 1998 1999 2000 2009 2010 2011
do  declare -a "y$year=($(printf "%s-$year " JF JFE RFS JBF JFI JMCB |
               tee /dev/fd/2 ))"
    year=y$year[@]; year=(${!year})
    echo "${#year[@]}"
done 2>&1; unset year

这是第二个命令的输出,但第一个命令打印的内容与 6 相同 - 它仅表示数组成员计数。

JF-1998 JFE-1998 RFS-1998 JBF-1998 JFI-1998 JMCB-1998 6
JF-1999 JFE-1999 RFS-1999 JBF-1999 JFI-1999 JMCB-1999 6
JF-2000 JFE-2000 RFS-2000 JBF-2000 JFI-2000 JMCB-2000 6
JF-2009 JFE-2009 RFS-2009 JBF-2009 JFI-2009 JMCB-2009 6
JF-2010 JFE-2010 RFS-2010 JBF-2010 JFI-2010 JMCB-2010 6
JF-2011 JFE-2011 RFS-2011 JBF-2011 JFI-2011 JMCB-2011 6

请记住,这declare是一个命令,而var$expand=(something $expand)参数只是一个 arg。declare的参数以与任何其他参数相同的方式扩展 - 这对于var$expand=$expand语句来说不是这样。因此,您可以间接地declare以同样的方式间接地export或其他方式 - 我认为您使用的硬引号是不必要的。

答案3

通过将大括号扩展转换为数组set --

然后你有一个简单的二维循环来构造你的输出:

set -- {JF,JFE,RFS,JBF,JFI,JMCB}
for year in {1998..2000} {2009..2011}; do
    printf "y%s: " $year
    for code do
        printf "%s-%s " $code $year
    done
    echo
done

产量:

y1998: JF-1998 JFE-1998 RFS-1998 JBF-1998 JFI-1998 JMCB-1998
y1999: JF-1999 JFE-1999 RFS-1999 JBF-1999 JFI-1999 JMCB-1999
y2000: JF-2000 JFE-2000 RFS-2000 JBF-2000 JFI-2000 JMCB-2000
y2009: JF-2009 JFE-2009 RFS-2009 JBF-2009 JFI-2009 JMCB-2009
y2010: JF-2010 JFE-2010 RFS-2010 JBF-2010 JFI-2010 JMCB-2010
y2011: JF-2011 JFE-2011 RFS-2011 JBF-2011 JFI-2011 JMCB-2011

相关内容