我想生成一些仅按年份不同的数组。在循环中,我创建带有大括号扩展和变量的数组。
我尝试了以下代码但没有成功:
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
我不需要打印它们,只需在循环中使用它们并将它们作为参数传递即可。因为第二个,eval
in-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
这些declare
s 并不是绝对必要的,但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