Bash 手册说大括号扩展是在任何其他扩展之前执行的。
我正在编写一个接受两个参数的脚本:
#! /bin/bash
for b in {$1..$2}; do echo $b; done
我像这样运行它:
$ ./myscript 0002 0010
{0002..0010}
输出不是我希望的。我希望在大括号扩展之前执行参数扩展。我的示例的预期输出是0002 0003 0004 0005 0006 0007 0008 0009 0010
, 不是2 3 4 5 6 7 8 9 10
。你会{$1..$2}
用什么来代替?
我希望该解决方案即使在$1
和$2
不仅由数字组成,而且由字母和数字组成的字符串中也能起作用。
请注意,值$1
和$2
只能作为脚本的参数给出。我认为从一开始就很清楚,但请指出以防万一。
答案1
执行您要求的操作:在大括号扩展之前执行参数扩展。
我们需要延迟大括号扩展,这可以通过引用它\{...\}
并调用 eval 轻松完成:
$ set -- 5 10
$ eval printf \'%s \' \{$1..$2\}
5 6 7 8 9 10
只要$1
或中没有命令,就可以正常工作$2
。
这是该解决方案的安全风险。缓解该问题的一种方法是确保变量仅包含数字:
#!/bin/bash
a=${1//[^0-9]/} ### select only numbers from first parameter.
b=${2//[^0-9]/} ### select only numbers from second parameter.
c=$(eval printf \'%s \' \{$a..$b\})
for i in $c; do echo "$i"; done
上面的代码缺少一些该版本更正的引用:
#!/bin/bash
a=${1//[^0-9]/} ### select only numbers from first parameter.
b=${2//[^0-9]/} ### select only numbers from second parameter.
c=( $(eval printf \'%s \' \{$a..$b\}) )
for i in "${c[@]}"; do echo "$i"; done
### Or just
# printf '%s\n' "${c[@]}"
但要打印数字列表,算术for
循环看起来是更好的解决方案:
#!/bin/bash
a=${1//[^0-9]/} ### select only numbers from first parameter.
b=${2//[^0-9]/} ### select only numbers from second parameter.
for (( i=$a; i<=$b; i++)); do
printf '%0*d\n' 5 "$i"
done
将其用作:
$ script.sh 5 15
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
答案2
支撑扩张不是由 POSIX 定义的,所以也许你可以完全放弃它:
seq $*
或者:
j=$1
while [ $j -le $2 ]
do
echo $j
j=$((j+1))
done
或者:
echo $* | awk '{for (j = $1; j <= $2; j++) print j}'
答案3
#! /bin/bash
seq -w $1 $2
这可能就是您发现的!