在awk变量中添加前导零

27

我在bash中的“for”循环内有以下awk命令:

awk -v pdb="$pdb" 'BEGIN {file = 1; filename = pdb"_" file ".pdb"}
 /ENDMDL/ {getline; file ++; filename = pdb"_" file ".pdb"}
 {print $0 > filename}' < ${pdb}.pdb 

这段代码读取一系列名为$pdb.pdb的文件,并将它们分成名为$pdb_1.pdb,$pdb_2.pdb,......$pdb_21.pdb等文件。但是,我想生成名称为$pdb_01.pdb,$pdb_02.pdb,......$pdb_21.pdb的文件,即向“file”变量添加填充零。

我尝试过使用printf以不同的方式进行格式化,但都没有成功。非常感谢您的帮助。


你知道数字会涨到多高吗?是两位数是最大的吗? - B Johnson
5个回答

43

以下是如何使用awk创建前导零:

# echo 1 | awk '{ printf("%02d\n", $1) }'
01
# echo 21 | awk '{ printf("%02d\n", $1) }'
21

%02替换为您需要的总位数,包括零。


1
请注意,这仅适用于直接将格式化的数字打印到输出的情况。如果您想在awk变量或函数中使用格式化的数字,则可能需要使用sprintf,如其他答案中所述。 - R.M.
这里 awk '{ printf "%0" $2 "d\n", $1 }' 很好用。 - tripleee

36

将输出中的file替换为sprintf("%02d", file).

或者使用filename = sprintf("%s_%02d.pdb", pdb, file);来完成整个任务。


到目前为止,我已尝试了第一种选项,它运行地非常好。非常感谢! - mirix

3

这样做可以避免使用昂贵的printf函数。第一个参数是需要填充的字符串,第二个参数是填充后的总长度。

echo 722 8 | awk '{ for(c = 0; c < $2; c++) s = s"0"; s = s$1; print substr(s, 1 + length(s) - $2); }'

如果您提前知道结果字符串的长度,可以使用简化版本(例如,8是您的限制):

echo 722 | awk '{ s = "00000000"$1; print substr(s, 1 + length(s) - 8); }'

在这两种情况下的结果均为 00000722

1
不知道按照什么标准会更快。在一个快速测试中,这个脚本的10000次迭代花费了42秒,而明显更简单的带有“printf”的变体只花费了35秒。 - tripleee

1

这是一个函数,根据参数左侧或右侧填充零:zeropad(value, count, direction)

function zeropad(s,c,d) {
    if(d!="r")             
        d="l"                # l is the default and fallback value
    return sprintf("%" (d=="l"? "0" c:"") "d" (d=="r"?"%0" c-length(s) "d":""), s,"")
}
{                            # test main
    print zeropad($1,$2,$3)
}

一些测试:

$ cat test
2 3 l
2 4 r
2 5
a 6 r

测试:

$ awk -f program.awk test
002
2000
00002
000000

它尚未经过全面的战场测试,因此奇怪的参数可能会产生奇怪的结果。


0
这是一种非常不寻常的利用OFS填充零的方法。
jot 10 1 - 12333337 | 

mawk '(___ = __ - length($_)) <= _ || $++___ = $_ ($_=_)' OFS=0 __=23

00000000000000000000001
00000000000000012333338
00000000000000024666675
00000000000000037000012
00000000000000049333349
00000000000000061666686
00000000000000074000023
00000000000000086333360
00000000000000098666697
00000000000000111000034

它们也不必是零。同样的方法也适用于填充表情符号:

jot 10 1 - 12333337 | 

mawk2 '  (___ = __-length($_)) <=_ || 
         $++___ = $_ ($_ = _)' OFS='\360\237\246\201' __=17 |

gawk -e '$++NF = length($1)'

1 17
12333338 17
24666675 17
37000012 17
49333349 17
61666686 17
74000023 17
86333360 17
98666697 17
111000034 17

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接