awk NR==FNR 命令语法
awk NR==FNR for command syntax
我在使用输入 .fastq 文件中的 awk
NR==FNR
至 return 行时遇到问题。
我有以下名为 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);i<=(+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);i<=(+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 命令的行为。
您的输入中没有冒号 (:
),因此 </code> 指的是整行,而 <code>(-1)
& (+2)
将是 -1
和 2
,这意味着您的 for
循环将始终 运行 恰好四次(对于 i
等于 -1
、0
的值, 1
, 然后 2
).
在 for
循环中,您要确保 a[i]
存在(即 a[-1]
、a[0]
、a[1]
和 a[2]
).
只要数组 a
包含一个条目,代码的最后部分就会打印当时正在检查的行(但由于前一节中的 next
而不是来自第一个文件)该文件的行号。因此,它从每个输入打印第 1 行和第 2 行(因为 a[FNR]
存在于 FNR
等于 1 或 2)。
由于您需要一个大概的答案,因此必须使用 agrep
, 提出的想法是有道理的,但它的实现(如上文所述)没有意义。
以下解决方案使用 agrep
的命中作为提示,让周围的行与命中一起打印(agrep
不支持上下文行,如 grep
的 -A NUM
和 -B num
否则我们可以做 agrep -A1 -B2 -1 -n PATTERN example.fastq
以获得更简单的答案)。
agrep -1 "GAAATAATA" example.fastq | awk '
NR == FNR { agrep_hit[[=10=]] = 1; next }
agrep_hit[[=10=]] { print last_line; i = 1 }
0 < i && i < 4 { i++; print }
{ last_line = [=10=] }
' - example.fastq
这将检查输入文件两次。第一次使用 agrep
查找近似模式匹配,而第二次使用 awk
获取请求的上下文行。
当 awk
(NR
) 中的总行号等于本地文件的行号 (FNR
) 时,这意味着我们正在检查第一个输入 (-
, 标准输入,即agrep
)的输出。我们将近似模式命中存储在关联数组中以备后用,然后使用 next
移动到下一行(因此 awk
命令的其余部分仅对以后的输入起作用)。
由于您需要上一行,我们必须显式打印它。 awk
代码的最后一节将当前行保存为 last_line
以便我们稍后检索它。在 agrep
输出的一行(因此存储在我们的数组中),我们打印保存 last_line
并将迭代器 i
设置为 1
.
当 i
为 1
、2
或 3
时,我们将其递增并打印当前行。这将打印匹配行,然后再打印两行作为上下文。
您可以使用这个 agrep + awk
解决方案:
srch() {
awk -F ': ' 'NR==FNR {
a[] = 1
next
}
a[FNR] {
print p
print
for (i=0; i<2 && getline > 0; i++)
print
}
{
p=[=10=]
}' <(agrep -1 -n "" "") ""
}
然后 运行 为:
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'
具有记录分隔符定义 (GNU awk
)
$ awk -v RS='(^|\n)@' '/GAAATAATA/{printf "%s", rt [=10=]} {rt=RT}' file
@SRR1111111.1 1/1
CTGGANAAGTGAAATAATATAAATTTTTCCACTATTGAATAAAAGCAACTTAAATTTTCTAAGTCG
+
AAAAA#EEEEEEEEEEEEEEEEEEEEEEEAEEEEEEEEEEEEEEEEEEEEEEEEEA<AAEEEEE<6
@SRR1111111.3 3/1
CTATANTATTGAAATAATAATGTAGATAAAACTATTGAATAACAGCAACTTAAATTTTCAATAAGA
+
AAAAA#EE6EEEEEEEEEEEEAAEEAEEEEEEEEEEEE/EAE/EAE/EA/EAEAAAE//EEAEAA6
我在使用输入 .fastq 文件中的 awk
NR==FNR
至 return 行时遇到问题。
我有以下名为 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);i<=(+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);i<=(+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 命令的行为。
您的输入中没有冒号 (:
),因此 </code> 指的是整行,而 <code>(-1)
& (+2)
将是 -1
和 2
,这意味着您的 for
循环将始终 运行 恰好四次(对于 i
等于 -1
、0
的值, 1
, 然后 2
).
在 for
循环中,您要确保 a[i]
存在(即 a[-1]
、a[0]
、a[1]
和 a[2]
).
只要数组 a
包含一个条目,代码的最后部分就会打印当时正在检查的行(但由于前一节中的 next
而不是来自第一个文件)该文件的行号。因此,它从每个输入打印第 1 行和第 2 行(因为 a[FNR]
存在于 FNR
等于 1 或 2)。
由于您需要一个大概的答案,因此必须使用 agrep
,
以下解决方案使用 agrep
的命中作为提示,让周围的行与命中一起打印(agrep
不支持上下文行,如 grep
的 -A NUM
和 -B num
否则我们可以做 agrep -A1 -B2 -1 -n PATTERN example.fastq
以获得更简单的答案)。
agrep -1 "GAAATAATA" example.fastq | awk '
NR == FNR { agrep_hit[[=10=]] = 1; next }
agrep_hit[[=10=]] { print last_line; i = 1 }
0 < i && i < 4 { i++; print }
{ last_line = [=10=] }
' - example.fastq
这将检查输入文件两次。第一次使用 agrep
查找近似模式匹配,而第二次使用 awk
获取请求的上下文行。
当 awk
(NR
) 中的总行号等于本地文件的行号 (FNR
) 时,这意味着我们正在检查第一个输入 (-
, 标准输入,即agrep
)的输出。我们将近似模式命中存储在关联数组中以备后用,然后使用 next
移动到下一行(因此 awk
命令的其余部分仅对以后的输入起作用)。
由于您需要上一行,我们必须显式打印它。 awk
代码的最后一节将当前行保存为 last_line
以便我们稍后检索它。在 agrep
输出的一行(因此存储在我们的数组中),我们打印保存 last_line
并将迭代器 i
设置为 1
.
当 i
为 1
、2
或 3
时,我们将其递增并打印当前行。这将打印匹配行,然后再打印两行作为上下文。
您可以使用这个 agrep + awk
解决方案:
srch() {
awk -F ': ' 'NR==FNR {
a[] = 1
next
}
a[FNR] {
print p
print
for (i=0; i<2 && getline > 0; i++)
print
}
{
p=[=10=]
}' <(agrep -1 -n "" "") ""
}
然后 运行 为:
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'
具有记录分隔符定义 (GNU awk
)
$ awk -v RS='(^|\n)@' '/GAAATAATA/{printf "%s", rt [=10=]} {rt=RT}' file
@SRR1111111.1 1/1
CTGGANAAGTGAAATAATATAAATTTTTCCACTATTGAATAAAAGCAACTTAAATTTTCTAAGTCG
+
AAAAA#EEEEEEEEEEEEEEEEEEEEEEEAEEEEEEEEEEEEEEEEEEEEEEEEEA<AAEEEEE<6
@SRR1111111.3 3/1
CTATANTATTGAAATAATAATGTAGATAAAACTATTGAATAACAGCAACTTAAATTTTCAATAAGA
+
AAAAA#EE6EEEEEEEEEEEEAAEEAEEEEEEEEEEEE/EAE/EAE/EA/EAEAAAE//EEAEAA6