使用 awk/sed 从特定字段中删除字符串

fri*_*day 5 sed awk regular-expression bioinformatics

我有一个看起来像这样的文件(> 80,000 行):

chr1    GTF2GFF chromosome  1   249213345   .   .   .   ID=chr1;Name=chr1
chr1    GTF2GFF gene    11874   14408   .   +   .   ID=DDX11L1;Note=unknown;Name=DDX11L1
chr1    GTF2GFF exon    11874   12227   .   +   .   Parent=NR_046018_1
chr1    GTF2GFF exon    12613   12721   .   +   .   Parent=NR_046018_1
chr1    GTF2GFF exon    13221   14408   .   +   .   Parent=NR_046018_1
chr1    GTF2GFF gene    14362   29370   .   -   .   ID=WASH7P;Note=unknown;Name=WASH7P
chr1    GTF2GFF exon    14362   14829   .   -   .   Parent=NR_024540
chr1    GTF2GFF exon    14970   15038   .   -   .   Parent=NR_024540
chr1    GTF2GFF exon    15796   15947   .   -   .   Parent=NR_024540
chr1    GTF2GFF exon    16607   16765   .   -   .   Parent=NR_024540
chr1    GTF2GFF exon    16858   17055   .   -   .   Parent=NR_024540
chr1    GTF2GFF exon    17233   17368   .   -   .   Parent=NR_024540
chr1    GTF2GFF exon    17606   17742   .   -   .   Parent=NR_024540
chr1    GTF2GFF exon    17915   18061   .   -   .   Parent=NR_024540
chr1    GTF2GFF exon    18268   18366   .   -   .   Parent=NR_024540
chr1    GTF2GFF exon    24738   24891   .   -   .   Parent=NR_024540
chr1    GTF2GFF exon    29321   29370   .   -   .   Parent=NR_024540
chr1    GTF2GFF gene    34611   36081   .   -   .   ID=FAM138A;Note=unknown;Name=FAM138A
chr1    GTF2GFF exon    34611   35174   .   -   .   Parent=NR_026818
chr1    GTF2GFF exon    35277   35481   .   -   .   Parent=NR_026818
Run Code Online (Sandbox Code Playgroud)

我只想提取第三个字段中包含“基因”的行,并重新排列第 9 个字段以仅包含 ID 值(例如,DDX11L1)。这是所需的输出:

chr1    11874   14408   DDX11L1    .       +
chr1    14362   29370   WASH7P      .       -
chr1    34611   36081   FAM138A    .       -
Run Code Online (Sandbox Code Playgroud)

使用 awk 我很容易得到了想要的字段:

head -20 genes.gff3 | awk '$3=="gene" {print $1 "\t" $4 "\t" $5 "\t" $9"\t" $6 "\t" $7}'
chr1    11874   14408   ID=DDX11L1;Note=unknown;Name=DDX11L1    .       +
chr1    14362   29370   ID=WASH7P;Note=unknown;Name=WASH7P      .       -
chr1    34611   36081   ID=FAM138A;Note=unknown;Name=FAM138A    .       -
Run Code Online (Sandbox Code Playgroud)

但我正在努力获取 ID 值。我试过用管道将它传输到 sed:

head -20 genes.gff3 | awk '$3=="gene" {print $1 "\t" $4 "\t" $5 "\t" $9"\t" $6 "\t" $7}' | sed 's/\(^.+\t\)ID=\(\w+\).+\(\t.+$\)/\1\2\3/g'
Run Code Online (Sandbox Code Playgroud)

还有 gsub

head -20 genes.gff3 | awk '$3=="gene" {gsub(/\(^.+\t\)ID=\(\w+\).+\(\t.+$\)/, "\1\2\3", $9); print $1 "\t" $4 "\t" $5 "\t" $9"\t" $6 "\t" $7}' 
Run Code Online (Sandbox Code Playgroud)

但结果与单独使用 awk 相同。如何提取 ID 值?我觉得我真的很接近这里的解决方案。

干杯。

gle*_*man 5

split函数的字段分隔符是一个正则表达式,因此您可以在=OR上进行拆分;。如果您知道以“ID=”$9 开头,那么

awk -v OFS='\t' '
    $3 == "gene" {
        split($9, id, /[=;]/)
        print $1, $4, $5, id[2], $6, $7
    }
' genes.gff3
Run Code Online (Sandbox Code Playgroud)

如果“ID=”不一定在字段的开头,那么还有一些工作要做:

awk -v OFS='\t' '
    $3 == "gene" {
        id = ""
        len = split($9, f, /[=;]/)
        for (i=1; i<len; i++) {
            if (f[i] == "ID") {
                id = f[i+1]
                break
            }
        }
        print $1, $4, $5, id, $6, $7    
    }
' genes.gff3
Run Code Online (Sandbox Code Playgroud)


Run*_*ium 3

您可以通过以下方式split字段和使用substr

\n
split($9, a, ";")\nprint substr(a[1], 4)\n
Run Code Online (Sandbox Code Playgroud)\n

awk 索引从 开始1

\n

另一种选择是修改输入字段分隔符 ( FS)。\nFS是空格," ",默认为 \xe2\x80\x93 ,它还具有忽略\n前导空格和尾随空格的特殊效果。

\n

另外,可以设置为制表符,而不是使用print $1, \\t, ...或变体。printfOFS

\n
\n

例子:

\n

修改FS:

\n
awk -F" +|;|=" \'\n\n$3 == "gene" {\n    printf("%s\\t%s\\t%s\\t%s\\t%s\\t%s\\t\\n",\n    $1, $4, $5, $10, $6, $7);\n}\n\' data.file\n
Run Code Online (Sandbox Code Playgroud)\n
\n

使用分割:

\n
awk \'\n$3 == "gene" {\n    split($9, a, ";")\n    printf("%s\\t%s\\t%s\\t%s\\t%s\\t%s\\t\\n",\n    $1, $4, $5, substr(a[1], 3), $6, $7);\n}\n\' data.file\n
Run Code Online (Sandbox Code Playgroud)\n
\n

OFS 和 FS:

\n

输出字段分隔符( OFS) 作为制表符,并FS在 awk 中替代。\n还更新FS为包含制表符:

\n
awk \'\nBEGIN {\n    FS="[ \\t]+|;|="\n    OFS="\\t"\n}\n$3 == "gene" {\n    print $1, $4, $5, $10, $6, $7\n}\n\n\' data.file\n
Run Code Online (Sandbox Code Playgroud)\n
\n

另请参阅开放组 变量和特殊变量示例

\n

Gawk 手册\xe2\x80\x93 当事物是 awk 的 gawk 扩展时,通常会注明。

\n