如何构建一个内部循环,使循环条件取决于外部循环的运行?
我的情况对于我正在寻找的代码可能并不重要,但情况是这样的:我有一个爬虫,我想在不断变化的 URL 上运行,其中 URL 取决于两个参数。第一个是年份,第二个是页面,而页面范围每年都会有所不同。
这是我到目前为止所尝试的
#!/bin/bash
numbers2004={625..721}
numbers2005={723..823}
for year in 2004 2005
do
for number in numbers$year
do
echo "$year $number"
done
done
它应该给我
2004 625
2004 626
...
2004 720
2004 721
2005 723
2005 724
...
2005 822
2005 823
答案1
使用当前的 bash 版本:
#!/bin/bash
declare -A numbers # declare associative array
printf -v numbers[2004] "%s " {625..721}
printf -v numbers[2005] "%s " {723..823}
for year in 2004 2005
do
for number in ${numbers[$year]}
do
echo "$year $number"
done
done
答案2
这是赛勒斯答案的一个变体,使用参数间接。然而,正如链接所说,基于数组的方法比使用间接方法更受青睐,因为这种间接方法是评估,应尽可能避免。
(我已经缩小了OP中给出的数字范围,只是为了使输出更小一些)。
#!/usr/bin/env bash
printf -v numbers2004 "%d " {625..635}
printf -v numbers2005 "%d " {723..733}
for year in 2004 2005
do
numbers="numbers$year"
for number in ${!numbers}
do
printf "%s %s\n" "$year" "$number"
done
done
输出
2004 625
2004 626
2004 627
2004 628
2004 629
2004 630
2004 631
2004 632
2004 633
2004 634
2004 635
2005 723
2005 724
2005 725
2005 726
2005 727
2005 728
2005 729
2005 730
2005 731
2005 732
2005 733
答案3
您还可以通过变量间接实现这一点:
#!/bin/bash
numbers2004="$(printf "%s " {625..721})"
numbers2005="$(printf "%s " {723..823})"
for year in 2004 2005
do
for number in $(eval echo \$numbers$year)
do
echo "$year $number"
done
done
答案4
你需要eval
按照你想要做的方式去做......
numbers2004={625..721}
numbers2005={723..823}
for year in 2004 2005
do
eval 'eval "for number in '"\$numbers$year"'
do
echo \"\$year \$number\"
done"'
done
...打印...
2004 625
...
2004 721
2005 723
...
2005 823
但这是一种可怕的方式 - 不仅因为引用是一场噩梦 - 但可能最重要的是因为你的 shell 完成了所有工作两次。它必须首先生成所有的{brace..expanded}
可迭代对象前然后迭代每个。
相反,也许:
y=4 n=623 c=721
while [ "$((y+=$c<(c+=102*(c<(n+=1<<(c==n))))))" -lt 6 ]
do echo "200$y $n"
done
busybox ash
...在最新版本的, ksh93
, dash
, yash
, bash
, zsh
, mksh
, 和中打印相同的内容posh
。
对于大多数算术表达式来说,通过仅在必要时评估其部分内容,可以使算术表达式的性能稍微提高一些,例如......
y=4 n=623 c=721
while [ "$((c<(n+=1)?(y+=(n+=1)<(c+=102)):y))" -lt 6 ]
do echo "200$y $n"
done
...它在上述所有 shell 中的工作原理相同,除了busybox
.它似乎busybox
总是评估if expr ? true : false
三元语句的所有方面,因此无法按预期进行迭代。