格式化命令的bash变量

时间:2009-01-19 20:03:49

标签: bash shell

从我的bash shell中我想用一个不同的编号参数调用一个程序n次,该参数必须是固定格式,如“%02i”

一种方法是:

for ((i=23; i<42;i++)); do 
    sh ../myprogram `printf "%02i\n" $i`
done

有没有办法改进printf..部分?我相信这可能是一个包含更多文件的性能瓶颈,并且使得该行的可读性低于内置函数(特别是在压缩为单行时)。

5 个答案:

答案 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