对于具有基于参数的范围的循环

时间:2014-09-24 14:12:57

标签: bash for-loop printf

我想对一组按字典顺序命名的文件(10-09之前的01-09)运行某些操作。我必须使用相当旧版本的FreeBSD(7.3),所以我不能使用像echo {01..30}seq -w 1 30这样的yummies。

我找到的唯一可行解决方案是printf "%02d " {1..30}。但是,我无法弄清楚为什么我不能使用$1$2而不是130。当我运行我的脚本(bash ~/myscript.sh 1 30)时,printf说{1..30}: invalid number

AFAIK,bash中的变量是无类型的,那么怎样才能将整数参数作为整数接受?

3 个答案:

答案 0 :(得分:0)

我猜你正在寻找这个伎俩:

#!/bin/bash
s=1
e=30
printf "%02d "  $(eval echo {$s..$e})

答案 1 :(得分:0)

Bash支持C风格的循环:

s=1
e=30
for i in ((i=s; i<e; i++)); do printf "%02d " "$i"; done

您尝试的语法不起作用,因为大括号扩展在参数扩展之前发生,所以当shell尝试展开{$1..$2}时,它仍然字面上 { {1}},而不是{$1..$2}


@Kent给出的答案有效,因为{1..30}回到解析过程的开始。我倾向于建议避免习惯性地使用它,如eval can introduce hard-to-recognize bugs - 如果你的命令被evalsudo列入白名单,那么$1, C-style-for-loop示例将安全地失败,而eval示例......则没那么多。

当然,执行权限提升攻击的人可能无法访问您编写的95%的脚本,但剩下的5%可能真的毁掉了一天;遵循良好做法100%的时间避免陷入邋habit的习惯。


因此,如果一个真的想要将一系列数字传递给一个命令,那么安全的做法就是将它们收集到一个数组中:

'$(rm -rf /; echo 1)'

答案 2 :(得分:0)

好的,我终于明白了!

#!/bin/bash
#BSD-only iteration method    
#for day in `jot $1 $2`
for ((day=$1; day<$2; day++))
do
    echo $(printf %02d $day)
done

我最初想在文件名中使用循环迭代器作为“日”,但现在我看到在我的确切情况下,更容易迭代正常数字(1,2,3等)并将它们处理成字典循环中的那些。在使用jot时,请记住$1是数字金额,而$2是起点。