awk - 如果特定列包含另一个文本文件中的元素作为子字符串,则删除一行

awk - 如果特定列包含另一个文本文件中的元素作为子字符串,则删除一行

我有以下 tsv 文件(摘录):

文件一:

NC_002163.1 RefSeq  source  1   1641481 .   +   .   organism=Campylobacter jejuni subsp. jejuni NCTC 11168;mol_type=genomic DNA;strain=NCTC 11168;sub_species=jejuni;db_xref=taxon:192222
NC_002163.1 RefSeq  misc_feature    19386   19445   .   -   .   inference=protein motif:TMHMM:2.0;note=3 probable transmembrane helices predicted for Cj0012c Further possible text
NC_002163.1 RefSeq  misc_feature    19482   19550   .   -   .   inference=protein motif:TMHMM:2.0;note=3 probable transmembrane helices predicted for Cj0014c Sometimes there is more text
NC_002163.1 RefSeq  misc_feature    22853   22921   .   -   .   inference=protein motif:TMHMM:2.0;note=5 probable transmembrane helices predicted for Cj0017c
...

如您所见,最后一列包含一些标识符 ( Cj0014c, Cj0017c, etc)。其中一些 ID 保存在另一个文件中

文件2:

Cj0012c
Cj0027
CjNC9
Cjp01
SRP_RNA_Cjs03
CjNC11
CjNC1
Cj0113
Cjp03
Cj0197c
Cj0251c

如何使用 awk (或任何 bash-script-tool)从文件 1 中消除这些行,其中包含子串在最后一列中,在文件 2 中找到任何 ID 吗?例如,文件 1 的第二行将被删除,因为它Cj0012c在文件 2 中找到并且是文件 1 中该行的最后一列中的字符串的一部分。

我已经挣扎了好几个小时了,所以感谢您的帮助(如果可能的话,还请对代码进行解释!)

答案1

您可以尝试以下几个选项 - 所有选项都基于从第二个文件构造关联数组,然后针对第一个文件的最后一个字段测试其元素,一旦找到匹配项就中断:

  1. 真正的子字符串匹配

    awk -F'\t' 'NR==FNR{a[$1]; next} {for(i in a) {if(index($NF,i)>0) next}} 1' File2 File1
    

    请注意(例如)这将标识Cj0012cABCj0012c和/或的子字符串Cj0012cdef

  2. 与上面类似,但在元素两侧填充一个空格字符,以防止部分单词匹配

    awk -F'\t' 'NR==FNR{a[$1]; next} {for(i in a) {if(index($NF," "i" ")>0) next}} 1' File2 File1
    

    a[" "$1" "](如果您愿意,您可以将字符串填充到数组赋值调用中)

  3. (可能需要 GNU awk)使用正则表达式匹配由File2包围的字符串组成的模式词边界锚

    gawk -F'\t' 'NR==FNR{a[$1]; next} {for(i in a) {if($NF ~ "\\<" i "\\>") next}} 1' File2 File1
    

    此版本的潜在问题是,如果 的元素File2可能包含正则表达式元字符 - 这些需要以某种方式转义。

答案2

一点 Perl 的知识:

perl -MList::Util=any -Mautodie -F'\t' -ane '
    BEGIN { open $f, "<", shift @ARGV; chomp(@exclusions = <$f>); }
    print unless any {$F[-1] =~ /\b\Q$_\E\b/} @exclusions; 
' file2 file1

BEGIN 行在文件中包含排除标记的列表。
打印行过滤掉与其中任何一行匹配的行。

相关内容