[英]awk reparse piped input without getline
我写了一个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
中有另一个选项可以解析管道输入两次吗?
只需将输入存储在一个数组中,然后打印即可。 你没有发布任何样本输入和预期输出,所以我们没有什么可以测试,但这样的东西可能是你想要的:
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]
}
}
'
实际上并没有更好的方法(编辑:实际上,如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 |
$
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.