如何删除AWK中的输入字段?

MLu*_*MLu 7 awk

我正在使用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. 只需要先去掉一些字段。

任何的想法?

cas*_*cas 7

在 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()执行与对输入字段执行的操作几乎相同的操作。