从我的bash shell中我想用一个不同的编号参数调用一个程序n次,该参数必须是固定格式,如“%02i”
一种方法是:
for ((i=23; i<42;i++)); do
sh ../myprogram `printf "%02i\n" $i`
done
有没有办法改进printf..
部分?我相信这可能是一个包含更多文件的性能瓶颈,并且使得该行的可读性低于内置函数(特别是在压缩为单行时)。
答案 0 :(得分:20)
在Bash中,printf
由shell提供(请参阅the bash(1) manpage,搜索“printf”),因此您甚至没有fork()
的(最小)开销exec()
执行单独的命令 - 除非你从反引号中运行它。 Bash的内置printf允许您使用-v
参数将输出分配给给定变量;您的脚本片段可以重写为:
for ((i=23; i<42;i++)); do
printf -v ii "%02i\n" $i
sh ../myprogram $ii
done
我不确定我认为它比原版更具可读性。
脚本片段中资源最密集的部分是调用其他shell脚本;我不担心调用printf的开销,除非进一步的证据表明不是这样。
编辑以添加反引号和直接执行之间的区别
答案 1 :(得分:6)
您的号码已有2位小数。为什么你需要使用printf呢?如果我没记错的话(这里没有测试shell),它只是在与这些标志一起使用时填充最多2位小数。就个人而言,我喜欢xargs:
seq 23 42 | xargs -n1 sh ../myprogram
您可以使用-w
seq
参数,如果需要,可以用零填充数字,因此它们具有相同的宽度。
事实证明seq
是特定于Linux的。感谢Dave在评论中找出它(他的answer)。直接使用printf
,无需循环:
printf '%02i\n' {23..42} | xargs -n1 sh ../myprogram
我喜欢使用xargs
,因为它可以轻松地并行运行命令达到某个限制,可以一次传递多个数字并允许其他灵活选项。和Dave一样,我建议你从它中删除sh
,然后将其放入shell脚本中,作为第一行:
#!/bin/sh
.....
然后只需执行你的东西
printf '%02i\n' {23..42} | xargs -n1 ../myprogram
这是更通用的,并允许您的脚本也被exec
C库调用调用(至少在Linux中,就是这种情况)。
答案 2 :(得分:2)
仅供参考:完全不同的解决方案:
jot -w "%02i" - 23 42 | xargs -n 1 ../myprogram
这具有调用jot的性能缺点(标准自4.2BSD以来所有BSD衍生产品都有它,但快速浏览表明这个基本的奇妙工具似乎缺少我看过的Linux发行版) 。 编辑:Linux(至少Red Hat)似乎在名为seq的命令中有一部分jot功能(感谢litb的answer获取此信息)。
这也有利于在非bash shell中工作(不像有些人认为的那样,有多个shell在主动使用,而shell不可知的解决方案通常是个好主意)。
答案 3 :(得分:1)
怎么样
for i in {23..42} ; do
sh ../myprogram $i
done
23到42之间的数字总是采用%02i格式。
如果你绝对必须格式化,那么
for i in {23..42} ; do
printf "%02i\n" | xargs -n1 sh ../myprogram $i
done
替换产生xargs的开销,以产生反引号的子shell的开销。我不知道哪个更有效率。
答案 4 :(得分:-1)
尝试:
seq -w 23 41
这将自动填充前导0到所需的大小
或:
seq -f "%02g" 1 29
这将格式化为精确的2位数。
如此完整的命令将是:
for i in `seq -f "%02g" 23 41`; do
sh ../myprogram $i
done