我真正怀念的一件事awk
是能够使用分隔符连接数组,就像join
Perl 中的命令一样,通常是为了立即输出。
相反,我最终会编写如下代码
for (key in array)
joined_string = (joined_string == "" ? array[key] : joined_string "," array[key])
print joined_string
或者
joined_string = array[1]
for (i = 2; i <= length(array); ++i)
joined_string = joined_string "," array[i];
print joined_string
但是,awk
如果我更改当前字段,可以为我执行此操作:
OFS="," # (would probably do this in BEGIN)
n = 0
for (key in array)
$(++n) = array[key]
print
我相信这是完全合法的。但是,如果当前输入记录的字段多于数组array
的条目数,这将在输出中产生垃圾(“垃圾”将是来自输入文件的数据)。因此,如果能够做到这一点就好了
OFS = "," # (would probably do this in BEGIN)
n = 0
for (key in array)
$(++n) = array[key]
NF = n
print
我在标准中找不到任何说明NF
允许修改的文本,但也没有任何文本说明不允许修改或调用未定义的行为。信息我能发现是getline
套NF
。这并不是说我不允许编写自己的函数或重置的代码块,而是在“函数”NF
存在的情况下优先执行此操作。getline
还指出$0
允许分配给并且这会重置NF
。这是否意味着下面的代码会更好?
OFS = "," # (would probably do this in BEGIN)
$0 = ""
n = 0
for (key in array)
$(++n) = array[key]
print
双重问题:
- 允许设置吗
NF
? - 最后一段代码是将数组与输出分隔符连接起来的正确方法吗?
答案1
据我所知没有标准记录设置副作用的文本NF
,甚至是否允许设置。 Gawk 手册(也出版为有效的awk
编程),这表示它尝试总体记录 Awk而不仅仅是 GNU 实现,包括以下内容:
递减
NF
会在新值NF
和 重新计算后丢弃字段的值$0
。 (直流)
带有警告
警告:某些版本的减少时
awk
不会重建。$0
NF
“(dc)”提及意味着这是一个Awk 的“黑暗角落”,IE文档记录很少(或根本没有),并且不同实现的行为可能有所不同。
POSIX 将特殊变量定义为
由设置的变量awk
但它没有指定它们是否可以由程序设置(作为一般规则)。一些变量的规范确实提到它们可以被修改(参见ARGC
,ARGV
),其他变量的规范提到更改它们的后果是实现定义的(ENVIRON
),其他变量仍然没有提及任何内容,但“显然”打算由程序(OFS
等)。
在 的例子中NF
,实验给出了部分答案:
- 修改
NF
GNU Awk 中记录的工作,并且mawk
行为方式相同; - 更改为
NF
在真正的 awk被保留,但不会导致$0
重新计算。
所以我想说
- 允许设置
NF
,但除了设置值之外可能不会有任何副作用。 - 自设定以来
$0
是由 POSIX 指定,根据规范,最后一个变体是正确的。 (是否是这样还有待商榷这正确的方法,因为它输了$0
。)
该函数在如何在 awk 中将数组转换为字符串?很有趣,但根据定义,它依赖于 GNU Awk 扩展,因此不是这个问题的答案。
(有些令人惊讶的是,其他可以设置的变量包括NR
和FNR
,包括 TOTA 中的 。FILENAME
但是,不能设置,或者更确切地说,设置它会清除其值。)