删除包含特定文本的列

Its*_*hng 6 sed awk patterns columns

我正在寻找一个选项来删除具有特定文本的列,例如

“滴滴”

aaa bbb ccc ddd eee fff
1   2   3   4   5   6
2   3   4   5   6   0
Run Code Online (Sandbox Code Playgroud)

所以输出看起来像这样:

aaa bbb ccc eee fff
1   2   3   5   6
2   3   4   6   0
Run Code Online (Sandbox Code Playgroud)

我知道有一个简单的选项可以删除第 4 列并且可以完成相同的工作,但是我的 *.csv 文件没有排序。有任何想法吗?

Joh*_*024 8

sed不是正确的工具。尝试awk

$ awk -v OFS='\t' 'NR==1{for (i=1;i<=NF;i++)if ($i=="ddd"){n=i-1;m=NF-(i==NF)}} {for(i=1;i<=NF;i+=1+(i==n))printf "%s%s",$i,i==m?ORS:OFS}' file
aaa     bbb     ccc     eee     fff
1       2       3       5       6
2       3       4       6       0
Run Code Online (Sandbox Code Playgroud)

这假设要删除的字符串ddd 在这种情况下显示为第一行中的字段。

这个怎么运作

  • -v OFS='\t'

    这将输出字段分隔符设置为选项卡。如果您正在使用其他东西,请更改此设置。

  • NR==1{for (i=1;i<=NF;i++)if ($i=="ddd"){n=i-1;m=NF-(i==NF)}}

    这将扫描第一行中的所有列。我们将带有ddd(减一)的列数保存在变量 中n

    它还设置m为最后一列的编号,除非i是最后一列,在这种情况下它将其设置为NF-1

  • for(i=1;i<=NF;i+=1+(i==n))printf "%s%s",$i,i==m?ORS:OFS

    这会打印出每个字段,跳过ddd出现在第一行中的字段。

    i+=1i在每个循环中递增1。 在每个循环中i+=1+(i==n)递增i1,除非i==n在这种情况下i递增 2。这具有跳过右列的效果。

    printf "%s%s",$i,i==m?ORS:OFS打印列i后跟列分隔符OFS或行分隔符ORS,具体取决于是否i是最后一列。

多行

对于那些喜欢这样写成多行命令的人:

awk -v OFS='\t' '

NR==1{
    for (i=1;i<=NF;i++)
        if ($i=="ddd") {
            n=i-1
            m=NF-(i==NF)
        }
    }

{
    for(i=1;i<=NF;i+=1+(i==n))
        printf "%s%s",$i,i==m?ORS:OFS
}

' file
Run Code Online (Sandbox Code Playgroud)

使用逗号分隔的文件

如果我们希望输入和输出以逗号分隔,我们需要同时更改输入字段分隔符(带-F)和输出字段分隔符。例如,考虑这个输入文件:

$ cat file2
aaa,bbb,ccc,ddd,eee,fff
1,2,3,4,5,6
2,3,4,5,6,0
Run Code Online (Sandbox Code Playgroud)

然后使用:

$ awk -F, -v OFS=, 'NR==1{for (i=1;i<=NF;i++)if ($i=="ddd"){n=i-1;m=NF-(i==NF)}} {for(i=1;i<=NF;i+=1+(i==n))printf "%s%s",$i,i==m?ORS:OFS}' file2
aaa,bbb,ccc,eee,fff
1,2,3,5,6
2,3,4,6,0
Run Code Online (Sandbox Code Playgroud)


ter*_*don 5

这在sed(大多数情况下)是可能的,但我怀疑它比使用其他工具更简单。最简单的方法是首先获取您想要的字段编号,然后通过文件打印其余部分。例如,在 Perl 中:

$ perl -lane 'if($.==1){for(0..$#F){$d=$_ if $F[$_] eq "ddd"}} 
              print "@F[0..$d-1] @F[$d+1..$#F]"' file
aaa bbb ccc eee fff
1 2 3 5 6
2 3 4 6 0
Run Code Online (Sandbox Code Playgroud)

然而,这搞砸了格式。如果这很重要,请改用 John1024 的答案

  • @john1024,显然我指的是你的弟弟。 (3认同)
  • 是的,我父母总是更喜欢他。 (3认同)