我正在编写一个接受两个参数的脚本:
#! /bin/bash
eval for i in {$1..$2}; do echo $i; done
我像这样运行它:
$ ./myscript 0002 0010
syntax error near unexpected token `do'
为什么会出现这个错误呢?
我想这可能是因为循环应该分组。但通过替换eval for i in {$1..$2}; do echo $i; done
为eval { for i in {$1..$2}; do echo $i; done; }
,错误仍然存在。
注意:我希望在大括号扩展之前使用eval
.我的示例所需的输出是0002 0003 0004 0005 0006 0007 0008 0009 0010
. (看在大括号扩展之前执行参数扩展?)
答案1
那是因为 shell 评估了;
,所以eval
没有看到它。
您必须转义任何 shell 特殊字符以延迟其计算,并且 pass 的字面意思是eval
:
eval for i in \{"$1".."$2"\}\; do echo \"\$i\"\; done
答案2
该行在第一个元字符处断开,即;
(在本示例中)。
该行:
eval for i in {$1..$2}; do echo $i; done
分为这样三个命令:
eval for i in {$1..$2};
do echo $i;
done
尝试do
在没有先前的for
, while
,的情况下执行 auntil
是行不通的。它将引发错误条件:
意外标记“do”附近出现语法错误
发生这种情况是因为前一个for
作为参数隐藏在命令中eval
。
一种可能的解决方法是引用所有内容并仅省略您想要扩展的内容,我相信您需要变量$1
和$2
:
eval 'for i in {'$1'..'$2'}; do echo $i; done'
它确实有效:
$ ./myscript 0002 0010
0002
0003
0004
0005
0006
0007
0008
0009
0010
然而,这个脚本正在eval
使用外部输入,这是一种非常不安全的做法。
正确的解决方案
一个更安全的脚本可以清理 $1 和 $2 并正确引用变量,如下所示:
#!/bin/bash
a=${1//[^0-9]/} ### select only numbers from first parameter.
b=${2//[^0-9]/} ### select only numbers from second parameter.
eval 'for i in {'"$a"'..'"$b"'}; do echo $i; done'