我正在使用awk
(或gawk
)转换一些数据,并希望在再次打印输出之前删除其中一个输入字段。
我想要实现的是:
~ $ echo 'field1,field2,field3' | awk -F, '{transform($1); delete($2); print $0;}'
new_field1,field3
我不能只分配一个空字符串,$2
因为这会导致new_field1,,field3
(注意两个逗号)。
我可以只显式地打印我想要的字段,但这不是很优雅,因为我的字段比 3 多得多,而且最后还有可选字段(此处未显示)。这就是为什么我更喜欢print $0
. 只需要先摆脱一些领域。
任何想法?
众所周知,在 awk 中删除字段非常困难。这似乎是一个如此简单(并且经常需要)的操作,但它比应有的更难。
请参阅有没有办法完全删除 awk 中的字段,以便不打印额外的分隔符? 来自 Stack Overflow 的一个好方法。
我已经
rmcol()
在@ghoti 的答案中复制了该函数,因此我们在 U&L 上有一个副本:它从当前输入行中删除指定的列并减少字段计数器 (
NF
) 以匹配。我不知道你的
transform()
函数是做什么的,所以我什至不会尝试复制它——但这里有一个在单行中使用的rmcol()
例子awk
:顺便说一句,如果您需要从输入行中删除多个字段,最好/最容易以相反的顺序删除它们。即先删除编号最高的字段。为什么?因为每次删除编号较低的字段时,编号较高的字段都会重新编号,因此很难跟踪哪个字段编号属于哪个字段。
顺便说一句,
delete()
inawk
用于删除数组的元素 - 不是用于从输入行中删除字段。您可以将split()
每个输入行 (onFS
) 放入一个数组并删除第二个数组元素,但随后您必须编写一个join()
函数来打印数组,并用逗号 (或OFS
) 分隔每个字段。即使这样做也会比预期的更复杂,因为其中的所有数组
awk
都是关联数组(即它们没有数字索引) - 所以delete(array[2])
不会自动将数组元素 3+ 转换为元素 2+。您必须编写自己的包装函数,才能对数组执行与输入字段delete()
几乎相同的操作。rmcol()
一些替代品
cut
1)预处理输入以首先删除字段,如果字段分隔符为单个字符,则易于处理2) 使用
perl
重写 $0
gensub
可能会导致更简单的脚本。要从给定的 input 中删除字段 2 和 3,您可以使用 $0 删除字段
gensub
并重新生成 $0(以及所有字段),如下所示:注意
print
相当于print $0
。