处理多个文件时快速 I/O
Fast I/O when working with multiple files
我有两个输入文件,我想将它们混合并将结果输出到第三个文件中。在下文中,我将使用玩具示例来解释文件的格式和所需的输出。每个文件包含重复的 4 行模式(但包含不同的序列),我只包含单个 4 行:
输入文件1:
@readheader1
ACACACACACACACACACACACACACACACACACACACACACACACACACACAC
+
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
...
输入文件2:
@readheader2
AATTAATT
+
FFFFFFFF
...
期望的输出:
@readheader1_AATTAATT
ACACACACACACACACACACACACACACACACACACACACACACACACACACAC
+
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
...
所以我想在 small sequence found in the second line of every four line from the second file
上使用下划线附加 first line of every four line from the first file
。我只是将第一行的每四行中的第 2n、第 3 和第 4 行按原样输出到输出中。
我正在寻找可以优化我以下内容的任何脚本(linux bash、python、c++ 等):
我写了这段代码来完成任务,但我发现它很慢(输入大小为 60 GB 和 15 GB 需要一天多的时间);请注意,输入文件采用 fastq.gz
格式,因此我使用 gzip:
打开它们
...
r1_file = gzip.open(r1_file_name, 'r') # input file 1
i1_file = gzip.open(i1_file_name, 'r') # input file 2
out_file_R1 = gzip.open('_R1_barcoded.fastq.gz', 'wb') # output file
r1_header = ''
r1_seq = ''
r1_orient = ''
r1_qual = ''
i1_seq = ''
cnt = 1
with gzip.open(r1_file_name, 'r') as r1_file:
for r1_line in r1_file:
if cnt==1:
r1_header = str.encode(r1_line.decode("ascii").split(" ")[0])
next(i1_file)
if cnt==2:
r1_seq = r1_line
i1_seq = next(i1_file)
if cnt==3:
r1_orient = r1_line
next(i1_file)
if cnt==4:
r1_qual = r1_line
next(i1_file)
out_4line = r1_header + b'_' + i1_seq + r1_seq + r1_orient + r1_qual
out_file_R1.write(out_4line)
cnt = 0
cnt += 1
i1_file.close()
out_file_R1.close()
然后我使用 2 个数据集制作了两个输出,我希望交错输出文件:第一个文件的 4 行,第二个文件的 4 行,第一个文件的 4 行,依此类推。 .
使用 paste
实用程序(来自 GNU coreutils)和 GNU sed
:
paste file1 file2 |
sed -E 'N; s/\t.*\n([^\t]*)\t(.*)/_\n/; N; N; s/\t[^\n]*//g' > file.out
如果文件被 gzip 压缩,则使用:
paste <(gzip -dc file1.gz) <(gzip -dc file2.gz) |
sed -E 'N; s/\t.*\n([^\t]*)\t(.*)/_\n/; N; N; s/\t[^\n]*//g' > file.out
注意:这假设文件 1 和文件 2 中没有制表符
解释: 假设 file1 和 file2 包含这些行:
文件 1:
Header1
ACACACACAC
XX
FFFFFFFFFFFF
文件 2:
Header2
AATTAATT
YY
GGGGGG
在paste
命令之后,行被合并,由TAB
s分隔:
Header1\tHeader2
ACACACACAC\tAATTAATT
XX\tYY
FFFFFFFFFFFF\tGGGGGG
上面的\t
表示制表符。这些行被馈送到 sed
。 sed
读取第一行,模式 space 变为
Header1\tHeader2
N
命令向模式 space 添加一个换行符,然后将输入的下一行 (ACACACACAC\tAATTAATT
) 附加到模式 space。模式 space 变为
Header1\tHeader2\nACACACACAC\tAATTAATT
并与正则表达式 \t.*\n([^\t]*)\t(.*)
匹配,如下所示。
Header1\tHeader2\nACACACACAC\tAATTAATT
||^^^^^^^||^^^^^^^^^^||^^^^^^^^
\t .* \n ([^\t]*) \t (.*)
|| || ||
\n
表示一个换行符。然后通过s/\t.*\n([^\t]*)\t(.*)/_\n/
命令将匹配的部分替换为_\n
。模式 space 变为
Header1_AATTAATT\nACACACACAC
两个N
命令读取接下来的两行。现在模式 space 是
Header1_AATTAATT\nACACACACAC\nXX\tYY\nFFFFFFFFFFFF\tGGGGGG
s/\t[^\n]*//g
命令删除 TAB(含)和换行符(不含)之间的 所有 部分。此操作后最终模式 space 是
Header1_AATTAATT\nACACACACAC\nXX\nFFFFFFFFFFFF
打印为
Header1_AATTAATT
ACACACACAC
XX
FFFFFFFFFFFF
我有两个输入文件,我想将它们混合并将结果输出到第三个文件中。在下文中,我将使用玩具示例来解释文件的格式和所需的输出。每个文件包含重复的 4 行模式(但包含不同的序列),我只包含单个 4 行:
输入文件1:
@readheader1
ACACACACACACACACACACACACACACACACACACACACACACACACACACAC
+
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
...
输入文件2:
@readheader2
AATTAATT
+
FFFFFFFF
...
期望的输出:
@readheader1_AATTAATT
ACACACACACACACACACACACACACACACACACACACACACACACACACACAC
+
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
...
所以我想在 small sequence found in the second line of every four line from the second file
上使用下划线附加 first line of every four line from the first file
。我只是将第一行的每四行中的第 2n、第 3 和第 4 行按原样输出到输出中。
我正在寻找可以优化我以下内容的任何脚本(linux bash、python、c++ 等):
我写了这段代码来完成任务,但我发现它很慢(输入大小为 60 GB 和 15 GB 需要一天多的时间);请注意,输入文件采用 fastq.gz
格式,因此我使用 gzip:
...
r1_file = gzip.open(r1_file_name, 'r') # input file 1
i1_file = gzip.open(i1_file_name, 'r') # input file 2
out_file_R1 = gzip.open('_R1_barcoded.fastq.gz', 'wb') # output file
r1_header = ''
r1_seq = ''
r1_orient = ''
r1_qual = ''
i1_seq = ''
cnt = 1
with gzip.open(r1_file_name, 'r') as r1_file:
for r1_line in r1_file:
if cnt==1:
r1_header = str.encode(r1_line.decode("ascii").split(" ")[0])
next(i1_file)
if cnt==2:
r1_seq = r1_line
i1_seq = next(i1_file)
if cnt==3:
r1_orient = r1_line
next(i1_file)
if cnt==4:
r1_qual = r1_line
next(i1_file)
out_4line = r1_header + b'_' + i1_seq + r1_seq + r1_orient + r1_qual
out_file_R1.write(out_4line)
cnt = 0
cnt += 1
i1_file.close()
out_file_R1.close()
然后我使用 2 个数据集制作了两个输出,我希望交错输出文件:第一个文件的 4 行,第二个文件的 4 行,第一个文件的 4 行,依此类推。 .
使用 paste
实用程序(来自 GNU coreutils)和 GNU sed
:
paste file1 file2 |
sed -E 'N; s/\t.*\n([^\t]*)\t(.*)/_\n/; N; N; s/\t[^\n]*//g' > file.out
如果文件被 gzip 压缩,则使用:
paste <(gzip -dc file1.gz) <(gzip -dc file2.gz) |
sed -E 'N; s/\t.*\n([^\t]*)\t(.*)/_\n/; N; N; s/\t[^\n]*//g' > file.out
注意:这假设文件 1 和文件 2 中没有制表符
解释: 假设 file1 和 file2 包含这些行:
文件 1:
Header1
ACACACACAC
XX
FFFFFFFFFFFF
文件 2:
Header2
AATTAATT
YY
GGGGGG
在paste
命令之后,行被合并,由TAB
s分隔:
Header1\tHeader2
ACACACACAC\tAATTAATT
XX\tYY
FFFFFFFFFFFF\tGGGGGG
上面的\t
表示制表符。这些行被馈送到 sed
。 sed
读取第一行,模式 space 变为
Header1\tHeader2
N
命令向模式 space 添加一个换行符,然后将输入的下一行 (ACACACACAC\tAATTAATT
) 附加到模式 space。模式 space 变为
Header1\tHeader2\nACACACACAC\tAATTAATT
并与正则表达式 \t.*\n([^\t]*)\t(.*)
匹配,如下所示。
Header1\tHeader2\nACACACACAC\tAATTAATT
||^^^^^^^||^^^^^^^^^^||^^^^^^^^
\t .* \n ([^\t]*) \t (.*)
|| || ||
\n
表示一个换行符。然后通过s/\t.*\n([^\t]*)\t(.*)/_\n/
命令将匹配的部分替换为_\n
。模式 space 变为
Header1_AATTAATT\nACACACACAC
两个N
命令读取接下来的两行。现在模式 space 是
Header1_AATTAATT\nACACACACAC\nXX\tYY\nFFFFFFFFFFFF\tGGGGGG
s/\t[^\n]*//g
命令删除 TAB(含)和换行符(不含)之间的 所有 部分。此操作后最终模式 space 是
Header1_AATTAATT\nACACACACAC\nXX\nFFFFFFFFFFFF
打印为
Header1_AATTAATT
ACACACACAC
XX
FFFFFFFFFFFF