我有以下 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
您可以尝试以下几个选项 - 所有选项都基于从第二个文件构造关联数组,然后针对第一个文件的最后一个字段测试其元素,一旦找到匹配项就中断:
真正的子字符串匹配
awk -F'\t' 'NR==FNR{a[$1]; next} {for(i in a) {if(index($NF,i)>0) next}} 1' File2 File1
请注意(例如)这将标识
Cj0012c
为ABCj0012c
和/或的子字符串Cj0012cdef
与上面类似,但在元素两侧填充一个空格字符,以防止部分单词匹配
awk -F'\t' 'NR==FNR{a[$1]; next} {for(i in a) {if(index($NF," "i" ")>0) next}} 1' File2 File1
a[" "$1" "]
(如果您愿意,您可以将字符串填充到数组赋值调用中)(可能需要 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 行在文件中包含排除标记的列表。
打印行过滤掉与其中任何一行匹配的行。