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