我无法使用awk
NR==FNR
从输入的.fastq文件返回感兴趣的行。
我有以下示例输入文件,名为example.fastq
@SRR1111111.1 1/1
CTGGANAAGTGAAATAATATAAATTTTTCCACTATTGAATAAAAGCAACTTAAATTTTCTAAGTCG
+
AAAAA#EEEEEEEEEEEEEEEEEEEEEEEAEEEEEEEEEEEEEEEEEEEEEEEEEA<AAEEEEE<6
@SRR1111111.2 2/1
CTATANTATTCTATATTTATTCTAGATAAAAGCATTCTATATTTAGCATATGTCTAGCAAAAAAAA
+
AAAAA#EE6EEEEEEEEEEEEAAEEAEEEEEEEEEEEE/EAE/EAE/EA/EAEAAAE//EEAEAA6
@SRR1111111.3 3/1
CTATANTATTGAAATAATAATGTAGATAAAACTATTGAATAACAGCAACTTAAATTTTCAATAAGA
+
AAAAA#EE6EEEEEEEEEEEEAAEEAEEEEEEEEEEEE/EAE/EAE/EA/EAEAAAE//EEAEAA6
我正在尝试提取包含感兴趣的字符串的四行的组,重要的是必须允许近似匹配,因此使用agrep代替grep。下面的示例有效。
agrep -1 -n "GAAATAATA" example.fastq | awk -F: 'NR==FNR{for(i=($1-1);i<=($1+2);i++)a[i];next}FNR in a' - example.fastq
上面的命令产生以下正确的输出。
@SRR1111111.1 1/1
CTGGANAAGTGAAATAATATAAATTTTTCCACTATTGAATAAAAGCAACTTAAATTTTCTAAGTCG
+
AAAAA#EEEEEEEEEEEEEEEEEEEEEEEAEEEEEEEEEEEEEEEEEEEEEEEEEA<AAEEEEE<6
@SRR1111111.3 3/1
CTATANTATTGAAATAATAATGTAGATAAAACTATTGAATAACAGCAACTTAAATTTTCAATAAGA
+
AAAAA#EE6EEEEEEEEEEEEAAEEAEEEEEEEEEEEE/EAE/EAE/EA/EAEAAAE//EEAEAA6
但是,如果我使用第二行中未包含的序列,则此命令仍将打印前两行,如以下示例所示。
agrep -1 -n "TAGATAAAACT" example.fastq | awk -F: 'NR==FNR{for(i=($1-1);i<=($1+2);i++)a[i];next}FNR in a' - example.fastq
@SRR1111111.1 1/1
CTGGANAAGTGAAATAATATAAATTTTTCCACTATTGAATAAAAGCAACTTAAATTTTCTAAGTCG
@SRR1111111.3 3/1
CTATANTATTGAAATAATAATGTAGATAAAACTATTGAATAACAGCAACTTAAATTTTCAATAAGA
+
AAAAA#EE6EEEEEEEEEEEEAAEEAEEEEEEEEEEEE/EAE/EAE/EA/EAEAAAE//EEAEAA6
感谢您帮助我了解此awk命令的行为。
答案 0 :(得分:1)
您的输入中没有冒号(:
),因此$1
代表整行,($1-1)
和($2+2)
将成为-1
和2
,这意味着您的for
循环将始终精确运行四次(对于i
等于-1
,0
,1
的值,然后是2
)。
在for
循环中,您确保存在a[i]
(即a[-1]
,a[0]
,a[1]
和a[2]
)
您的代码的最后一部分将打印当时正在检查的行(但由于前一个节中的next
而不会从第一个文件打印),只要数组a
包含该行的条目文件的行号。因此,它从每个输入中打印第1行和第2行(因为a[FNR]
等于1或2的情况下存在FNR
。
由于您需要一个近似的答案,因此必须使用agrep
,James Brown's answer to your other question提出的想法很有意义,但其实现(如上文所述)没有意义。
以下解决方案使用agrep
的匹配作为围绕匹配行打印的提示(agrep
不支持grep
的{{1}}和-A NUM
,否则我们可以-B num
来获得更简单的答案)。
agrep -A1 -B2 -1 -n PATTERN example.fastq
这将两次检查输入文件。第一次使用agrep -1 "GAAATAATA" example.fastq | awk '
NR == FNR { agrep_hit[$0] = 1; next }
agrep_hit[$0] { print last_line; i = 1 }
0 < i && i < 4 { i++; print }
{ last_line = $0 }
' - example.fastq
查找近似模式匹配,而第二次使用agrep
获取请求的上下文行。
当awk
(awk
)中的总行号等于本地文件的行号(NR
)时,这意味着我们正在检查第一个输入(FNR
,即标准输入,即-
的输出)。我们将近似模式命中存储在关联数组中以备后用,然后使用agrep
移至下一行(因此,其余next
命令仅在以后的输入中起作用)。
由于您需要上一行,因此我们必须显式打印它。 awk
代码的最后一个节将当前行另存为awk
,以便我们稍后进行检索。在last_line
输出的行(并因此存储在数组中)上,我们打印保存的agrep
并将迭代器last_line
设置为i
。
当1
为i
,1
或2
时,我们将其递增并打印当前行。这将打印出匹配的行,然后再打印出两行以显示上下文。
答案 1 :(得分:1)
您可以使用以下agrep + awk
解决方案:
srch() {
awk -F ': ' 'NR==FNR {
a[$1] = 1
next
}
a[FNR] {
print p
print
for (i=0; i<2 && getline > 0; i++)
print
}
{
p=$0
}' <(agrep -1 -n "$2" "$1") "$1"
}
然后以以下方式运行它:
srch file 'GAAATAATA'
@SRR1111111.1 1/1
CTGGANAAGTGAAATAATATAAATTTTTCCACTATTGAATAAAAGCAACTTAAATTTTCTAAGTCG
+
AAAAA#EEEEEEEEEEEEEEEEEEEEEEEAEEEEEEEEEEEEEEEEEEEEEEEEEA<AAEEEEE<6
@SRR1111111.3 3/1
CTATANTATTGAAATAATAATGTAGATAAAACTATTGAATAACAGCAACTTAAATTTTCAATAAGA
+
AAAAA#EE6EEEEEEEEEEEEAAEEAEEEEEEEEEEEE/EAE/EAE/EA/EAEAAAE//EEAEAA6
这:
srch file 'TAGATAAAACT
@SRR1111111.3 3/1
CTATANTATTGAAATAATAATGTAGATAAAACTATTGAATAACAGCAACTTAAATTTTCAATAAGA
+
AAAAA#EE6EEEEEEEEEEEEAAEEAEEEEEEEEEEEE/EAE/EAE/EA/EAEAAAE//EEAEAA6'
答案 2 :(得分:0)
具有记录分隔符定义(GNU awk
)
$ awk -v RS='(^|\n)@' '/GAAATAATA/{printf "%s", rt $0} {rt=RT}' file
@SRR1111111.1 1/1
CTGGANAAGTGAAATAATATAAATTTTTCCACTATTGAATAAAAGCAACTTAAATTTTCTAAGTCG
+
AAAAA#EEEEEEEEEEEEEEEEEEEEEEEAEEEEEEEEEEEEEEEEEEEEEEEEEA<AAEEEEE<6
@SRR1111111.3 3/1
CTATANTATTGAAATAATAATGTAGATAAAACTATTGAATAACAGCAACTTAAATTTTCAATAAGA
+
AAAAA#EE6EEEEEEEEEEEEAAEEAEEEEEEEEEEEE/EAE/EAE/EA/EAEAAAE//EEAEAA6