使用字符串在bash中进行循环控制

时间:2015-02-12 20:32:26

标签: bash

我想用一个字符串来控制bash中的for循环。我的第一个测试代码产生了我期望的和我想要的东西:

$ aa='1 2 3 4'
$ for ii in $aa; do echo $ii; done
1
2
3
4

我想使用类似以下内容的东西。这不会给出我想要的输出(我可以看到它为什么会这样做)。

$ aa='1..4'
$ for ii in $aa; do echo $ii; done
1..4

有关如何修改第二个示例以提供与第一个示例相同的输出的任何建议吗?

提前感谢任何想法。我正在慢慢学习bash但仍有很多需要学习的东西。

麦克

4 个答案:

答案 0 :(得分:2)

符号可以写成:

for ii in {1..4}; do echo "$ii"; done

{1..4}需要写出来,不涉及变量,也不是变量替换的结果。这是Bash手册中的brace expansion,它发生在字符串扩展等之前。您可能最好使用:

for ii in $(seq 1 4); do echo "$ii"; done

其中1或4或两者都可以是shell变量。

答案 1 :(得分:2)

您可以使用seq命令(请参阅man seq)。

$ aa='1 4'
$ for ii in $(seq $aa); do echo $ii; done

答案 2 :(得分:1)

Bash不会使用变量执行brace expansion,但您可以使用eval

$ aa='1..4'
$ for ii in $(eval echo {$aa}); do echo $ii; done
1
2
3
4

您也可以将aa拆分为数组:

IFS=. arr=($aa) 
for ((ii=arr[0]; ii<arr[2]; ii++)); do echo $ii; done

请注意,IFS只能是单个字符,因此..范围会将数字放入索引0和2中。

答案 3 :(得分:0)

注意肯定有更优雅的方式,正如Ben Grimm的回答,这不是纯粹的bash,因为使用seq和awk。

实现此目标的一种方法是致电seq。如果您事先知道字符串中的数字,那将是微不足道的,因此不需要进行任何转换,因为您可以简单地执行seq 1 4seq $a $b

但是,我假设您的输入确实是您提到的格式的字符串,即1..420..100。为此,您可以将字符串转换为2个数字,并将它们用作seq的参数。

实现这一目标的可能方法之一是:

$ `echo "1..4" | sed -e 's/\.\./ /g' | awk '{print "seq", $1, $2}'`
1
2
3
4

请注意,对于给定格式的任何输入,这将以相同的方式工作。如果需要,sed可由tr更改,但结果相似。

$ x="10..15"
$ `echo $x | tr "." " " | awk '{print "seq", $1, $2}'`
10
11
12
13
14
15