我想从我的爆炸结果中提取命中和无命中 id。
例如我的爆炸输出包含:
> Query= TRINITY_DN109574_c0_g1_i1
Length=277
***** No hits found *****
Lambda K H a alpha
0.318 0.134 0.401 0.792 4.96
Gapped
Lambda K H a alpha sigma
0.267 0.0410 0.140 1.90 42.6 43.6
Effective search space used: 749080088160
> Query= TRINITY_DN109587_c0_g1_i1
Length=312
***** No hits found *****
Lambda K H a alpha
0.318 0.134 0.401 0.792 4.96
Gapped
Lambda K H a alpha sigma
0.267 0.0410 0.140 1.90 42.6 43.6
> Query= TRINITY_DN109586_c0_g2_i1
Length=472
Sequences producing significant alignments:
(Bits) Value
protein LOC111635341 n=1... 104 1e-23
UniRef90_UPI000C6CD8E3 uncharacterized protein LOC111632564 n=1... 103 1e-23
UniRef90_UPI000C6CAADE uncharacterized protein LOC111636326 n=1... 103 3e-23
我想像下面这样:
TRINITY_DN109574_c0_g1_i1 No hits
TRINITY_DN109587_c0_g1_i1 No hits
TRINITY_DN109586_c0_g2_i1 Sequences producing significant alignments:
这意味着我需要打印其他文件中每个查询的第二行。
答案1
sed -E "/^$/d" file | awk '/> Query/{printf "%s\t", $3; nr[NR+2]}; NR in nr '
输出
TRINITY_DN109574_c0_g1_i1 ***** No hits found *****
TRINITY_DN109587_c0_g1_i1 ***** No hits found *****
TRINITY_DN109586_c0_g2_i1 Sequences producing significant alignments:
演练...
您的 ID 和命中行间距会根据您是否命中而有所不同,但间距仅因额外的空行而有所不同,因此如果我们删除所有空行
sed -E "/^$/d" file
那么命中/未命中行始终位于查询之前 2 行。然后我们通过管道将|
其插入awk
以仅查找作为查询开始的那些行
awk '/> Query/'
$3
但我们只需要查询行中的第三个(空格分隔)字段,因为那是您的 ID
awk '/> Query/{print $3}'
每当我们找到正则表达式匹配时,我们还想计算匹配的 Hits 行的行号并将其存储在数组中。我已经调用了数组nr
,我们感兴趣的 Hits 行是当前匹配行NR
+2
awk '/> Query/{print $3; nr[NR+2]}'
NR
最后添加第二个条件来检查数组中是否存在与正则表达式不匹配的行nr
并打印它。还将第一个更改print
为printf
,以便在 ID 末尾输出 Hits。
awk '/> Query/{printf "%s\t", $3; nr[NR+2]}; NR in nr;'
请注意,如果添加的数字NR
超过下一个正则表达式匹配,则此解决方案将中断。
答案2
使用 GNU sed,我们从查询行开始在模式空间中累积行,不断丢弃空行,并在累积 3 个非空行时打印。
$ sed -e '
:loop
/\n.*\n/{
s//\t/
s/^> Query=//p
}
/^> Query=/!d
$d;N
s/\n$//
bloop
' file
使用 Perl,我们读取文件并获取查询行,跳过任何空行,跳过第一个非空行
$ perl -0777ne 'print "$1\t$2" while /^> Query=\h+(.*)\n\n*.*\n\n*(.*\n)/mg' file
答案3
在 PCRE 模式下使用 GNU grep,我们首先提取查询行,然后是 2 个非空行,中间空行可以从零到多个不等。
$ < file grep -zoP '(?m:^> Query=\h+\K.*\n\n*(.*\n\n*){2})' |
tr -d '\0' | tr -s '\n' |
sed -e 'h;n;n;H;g;s/\n/\t/'
使用范围运算符的另一种方法...
:
$ perl -lane '
$e = (/^> Query=/ && $c==0) ... (/\S/ && $c==2);
next if !length($e) || !@F;
$q = $F[2] if $e == 1;
print "$q\t$_" if $e =~ /E0/;
$c = $c == 2 ? 0 : $c+1;
' file