如何在 AWK 中一次删除多个列和字段分隔符?

Posted

技术标签:

【中文标题】如何在 AWK 中一次删除多个列和字段分隔符?【英文标题】:How to remove several columns and the field separators at once in AWK? 【发布时间】:2012-11-01 22:46:15 【问题描述】:

我有一个包含数千列的大文件。我想在 Bash 中使用 AWK 一次删除一些特定的列和字段分隔符。

我可以用这个 oneliner 一次删除一列(将删除第 3 列及其对应的字段分隔符):

awk -vkf=3 -vFS="\t" -vOFS="\t" 'for(i=kf; i<NF;i++) $i=$(i+1);; NF--; print' < Big_File

但是,我想一次删除几列...有人可以帮我解决这个问题吗?

【问题讨论】:

不,不是。在这里您选择特定列,而不是区间内的列... 我不同意。在上述两个问题中,都会出现删除范围和列列表的答案。 对于 AWK,我真的找不到... 我的投票太仓促了。事实上,这两个问题都有关于如何使用cut 的答案,但不是awk。投票重新开放。 【参考方案1】:

这是卡米尔想法的一个实现:

awk -v remove="3,8,5" '
  BEGIN 
    OFS=FS="\t"
    split(remove,a,",")
    for (i in a) b[a[i]]=1
                                                            
  
    j=1
    for (i=1;i<=NF;++i) 
      if (!(i in b))  
        $j=$i
        ++j
      
    
    NF=j-1
    print
  
'

【讨论】:

谢谢,但是那个脚本改变了字段分隔符,我想继续使用“tab”作为分隔符,知道吗? 不在 -v 和变量赋值之间放置空格会使您的解决方案不必要地特定于 gawk。此外,如果您要将 FS 和 OFS 设置为相同的值,则只需在 BEGIN 部​​分中使用 FS=OFS="\t" 会更简洁。【参考方案2】:

这样的事情应该可以工作:

awk -F'\t' -v remove='3|8|5' '

   rec=ofs=""
   for (i=1;i<=NF;i++) 
      if (i !~ "^(" remove ")$" ) 
         rec = rec ofs $i
         ofs = FS
      
   
   print rec

' file

【讨论】:

【参考方案3】:

如果您可以使用cut 而不是awk,则使用cut 会更容易:

例如这会从文件中获得第 1,3 列和第 50 列:

cut -f1,3,50- file

【讨论】:

【参考方案4】:

您可以将要从 shell 中删除的列列表传递给 awk,如下所示:

awk -vkf="3,5,11" ...

然后在awk程序中解析成数组:

split(kf,kf_array,",")

然后遍历所有列并测试每个特定列是否在 kf_array 中并可能跳过它

另一种可能性是多次致电您的 oneliner :-)

【讨论】:

以上是关于如何在 AWK 中一次删除多个列和字段分隔符?的主要内容,如果未能解决你的问题,请参考以下文章

AWK多个字段分隔。 AND语句

shell中 sed或awk 通过分隔符删除相应字段

awk 如何去除最后一个分隔字符

linux shell 中 awk 分隔符

awk基础

关于 linux shell awk 分隔符