在Bash脚本中传递到for循环的参数

25

我试图像这样将参数作为for循环的最大限制:

#!/bin/bash

for i in {1..$1}
do
    echo $i
done

但是,当用参数2调用它时,它返回{1..2},而不是执行脚本并给出结果。

1
2
4个回答

43

花括号内部不会进行变量替换。你可以使用固定的数字,但不能使用变量。

花括号展开

序列表达式采用{x..y}的形式,其中x和y是整数或单个字符。...

花括号展开在任何其他展开之前执行,并且任何特定于其他展开的字符都会保留在结果中。它是严格文本的。Bash不会将任何语法解释应用于扩展的上下文或花括号之间的文本。

正确形成的花括号扩展必须包含未引用的打开和关闭花括号,并且至少有一个未引用的逗号或有效的序列表达式。任何格式不正确的花括号扩展都将保持不变。

尝试其中一种替代方案:

for ((i = 1; i <= $1; i++)); do
    echo $i
done

# Not recommended with large sequences.
for i in $(seq 1 $1); do
    echo $i
done

1
你的解决方案是正确的,但你的推理是错误的。花括号扩展发生在变量替换之前,但{1..$1}不是有效的花括号扩展。 - Ignacio Vazquez-Abrams
谢谢,第一个解决方案可以解决问题(第二个方案已经过时)。你可能需要将“2”更改为“$1”以适应我的原始问题。 - Milo Wielondek
ksh93zsh的扩展顺序不同:ksh93 -c 'n=3; for i in {1..$n}; do echo $i; done' - Dennis Williamson
出于好奇,你能解释一下为什么不建议在大序列中使用 $(seq 1 $1) 吗?我猜测 seq 在那里会有显著的性能下降,但如果一些用户认为这与一般的 for 循环语法有关(即明确表明这不是一个 ARG_MAX 问题),解释可能仍然有用。 - Reinstate Monica Please

7

这将循环遍历所有为真的参数(也称为“testo mesto”是一个参数)

#cycle through all args
for (( i=1; i<=$1; i++ )); do
    eval arg=\$$i
    echo "$arg"
done

或者

#cycle through all args
for (( i=1; i<=$1; i++ )); do
    echo "${!i}"
done

4

除了John Kugelman的解决方案外,您还可以像这样使用eval

x=10; for i in $(eval echo {1..$x}); do echo $i; done

或者,如果$1是10,则:

set -- 10
for i in $(eval echo {1..$1})
do
    echo $i
done

您也可以使用以下一些变体:

set -- 1000
eval echo {1..$1} |
while read i
do
    echo $i
done

或者:

set -- 1000
while read i
do
     echo $i
done <(eval echo {1..$1})

那使用进程替换。


不错的技巧!如果我们想要一个前导零,Brace Expansion的效果很好。例如:for n in {001..10}; do echo $n; done - undefined

4

...或者在极少情况下,您只需要顺序编号:

seq $1

:-)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接