删除与第一行中的子字符串匹配的制表符分隔列

删除与第一行中的子字符串匹配的制表符分隔列

我想从标题(第一行)包含字符串“_HET”的文本文件中删除所有制表符分隔的列。输入文本文件如下所示:

rs36810213_HET   rs2438689   rs70927523570_HET   rs54666437   ...
1                0           2                   0
0                1           0                   1
2                0           1                   1
...              ...         ...                 ...

输出文本文件应如下所示:

rs2438689   rs54666437   ...
0           0
1           1
0           1
...         ...

我正在使用的代码不会删除任何内容:

#!/bin/bash

path="/data/folder"

awk -v OFS='\t' '

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

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

' $path/input.txt >> $path/output.txt

关于如何修复此代码有什么建议吗?谢谢你!

答案1

awk -F '\t' -f script.awk file

哪里script.awk

BEGIN { OFS = FS }

FNR == 1 {
    for (i = 1; i <= NF; ++i)
        if ($i !~ /_HET/)
            keep[i] = 1
}

{
    nf = split($0, fields, FS)
    $0 = ""
    j = 0

    for (i = 1; i <= nf; ++i)
        if (i in keep)
            $(++j) = fields[i]

    print
}

首先解析第一行的标头,并记住我们有兴趣将哪些标头保留在keep关联数组中。

然后,对于每一行,它仅从我们想要保留的字段重新创建当前记录(行),并打印它。

它通过将当前字段分隔符上的行(重新)分割到数组中fields,然后清空来实现此目的全部fields(带有$0 = ""; 这将重置NF),最后仅分配作为数组fields中键的字段keep

有些人喜欢说俏皮话:

awk -F '\t' -v OFS='\t' 'FNR==1{for(i=1;i<=NF;++i)if($i!~/_HET/)k[i]=1}{n=split($0,f,FS);$0=j="";for(i=1;i<=n;++i)if(i in k)$(++j)=f[i]}1' file

我没有完全遵循您的代码,但$i=="_HET"会将i:th 字段与 string进行比较_HET。除非该字段的值为确切地 _HET(你的标题字段都不是)。


一种完全不同的方法:

cut -f "$( awk -F '\t' -v OFS="," '{for(i=1;i<=NF;++i)if($i!~/_HET/)k[i]=1;$0="";for(i in k)$(++j)=i;print;exit}' file )" file

这个使用awk程序

BEGIN { OFS = "," }

{
    for (i = 1; i <= NF; ++i)
        if ($i !~ /_HET/)
            keep[i] = 1

    $0 = ""

    for (i in keep)
        $(++j) = i

    print
    exit
}

不输出内容所需列的数量,但将其列号输出为逗号分隔的字符串。然后使用该字符串cut从数据中删除列。

答案2

您可以使用 Perl 执行此操作,如下所示:

$ perl -F'/\t/' -pale '$"="\t";
    $. == 1 and @A = grep { $F[$_] !~ /_HET/ } 0 .. $#F;
    $_ = "@F[@A]";
' input.tsv

相关内容