我写了一个awk脚本,它将解析管道输入并将其转换为间隔很大的表。 为此,我需要解析输入流两次。首先解析每列的实际列大小。然后打印表本身。
#!/bin/gawk -f
# with changes from ooga
BEGIN {
FS=" "
buffer = "mktemp" | getline result
# Initialize Vars
}
{
# Count Columns...
}
END{
close(buffer)
while((getline < buffer) > 0){
# Print formated table
}
}
所以这项工作正常,但它使用getline
并且所有手册都指出,很少有真正需要getline
的情况。我认为唯一的其他选择是使用文件而不是管道。
gawk
中有另一个选项可以解析管道输入两次吗?
答案 0 :(得分:2)
只需将输入存储在数组中然后打印即可。你没有发布任何样本输入和预期输出,所以没有什么我们可以测试,但这样的东西可能是你想要的:
awk '
{
line[NR] = $0
curLength = length($0)
if (curLength > maxLength)
maxLength = curLength
}
END {
for (i=1; i<=NR; i++) {
printf "| %*s |\n", maxLength, line[i]
}
}
'
答案 1 :(得分:1)
这并不是一个更好的方法(编辑:实际上,正如Ed Morton所说,使用数组可能更好;看看他的帖子和我在这个结尾的替代例子但是,这不是一个非常糟糕的问题。程序,因为它没有使用pattern{action}
范例。 awk
对此程序的唯一优势是自动字段拆分。
一些提示:
FS
默认为单个空格(具有特殊含义,即字段由空格的运行分隔,并且忽略前导和尾随空格。)因此无需明确将它设置为空格。
|&
打开一个协同进程,但您只需要一个常规管道,所以只需|
。
您应该明确关闭管道。
这个功能似乎是一个不必要的并发症。
您应该在完成后删除临时文件。
这会产生:
#!/bin/gawk -f
BEGIN {
"mktemp" | getline tmpfile
close("mktemp")
}
{
# process and save piped data to tmpfile
}
END {
close(tmpfile)
while((getline < tmpfile) > 0) {
# process data from tmpfile
}
system("rm " tmpfile)
}
以下是使用数组而不是临时文件的示例:
#!/bin/awk -f
{
line[NR] = $0
if (NF > nf)
nf = NF;
for (i=1; i<=NF; ++i)
if (length($i) > flen[i])
flen[i] = length($i)
}
END {
for (r=1; r<=NR; ++r) {
for (f=1; f<=nf; ++f) {
split(line[r], fields)
printf("| %-*s ", flen[f], fields[f])
}
print "|"
}
}
输出:
$ cat file
one two three
four five six
seven eight nine
$ cat file | ./columnize.awk
| one | two | three |
| four | five | six |
| seven | eight | nine |
$