内循环条件取决于外循环运行

内循环条件取决于外循环运行

如何构建一个内部循环,使循环条件取决于外部循环的运行?

我的情况对于我正在寻找的代码可能并不重要,但情况是这样的:我有一个爬虫,我想在不断变化的 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三元语句的所有方面,因此无法按预期进行迭代。

相关内容