在大括号扩展之前执行参数扩展?

在大括号扩展之前执行参数扩展?

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

这可能就是您发现的!

相关内容