优化Bash脚本:高效比对文件第2、4列行对以缩短运行时间
高效解决方案:替换慢速Bash脚本
你的原始脚本运行缓慢的核心原因是每次循环都调用多个外部命令(sed、cut、cmp、wc),且反复读取磁盘上的文件。对于1732行数据,会产生约150万次外部进程调用和文件读取操作,这是巨大的性能瓶颈。
以下是两种高效的替代方案,均只需读取文件一次,所有处理在内存中完成:
方案1:使用Awk脚本(推荐,最快)
Awk专为文本处理设计,所有操作在单个进程内完成,无需频繁调用外部工具。
脚本代码(保存为collision.awk)
function abs(x) { return x < 0 ? -x : x } function count_diff(s1, s2) { diff = 0 len1 = length(s1) len2 = length(s2) min_len = len1 < len2 ? len1 : len2 for (i = 1; i <= min_len; i++) { if (substr(s1, i, 1) != substr(s2, i, 1)) { diff++ } } diff += abs(len1 - len2) return diff } BEGIN { FS = "[[:space:]]+" # 处理空格/制表符分隔的字段 } NR == 1 { next } # 跳过表头行 { # 用单空格连接字段,保证输出格式一致 lines[NR] = $1 " " $2 " " $3 " " $4 " " $5 idx2[NR] = $2 idx4[NR] = $4 } END { num_lines = NR output_file = "primer_collision.txt" for (i = 2; i <= num_lines; i++) { for (j = i + 1; j <= num_lines; j++) { diff2 = count_diff(idx2[i], idx2[j]) diff4 = count_diff(idx4[i], idx4[j]) if (diff2 < 3 && diff4 < 3) { print lines[i] > output_file print lines[j] > output_file print "" > output_file } } } close(output_file) }
运行命令
awk -f collision.awk Lab_primers.tsv
方案2:使用Python脚本(更易读,跨平台)
如果你更熟悉Python,这个方案同样高效,逻辑与Awk一致:
脚本代码(保存为collision.py)
def count_diff(s1, s2): diff = 0 min_len = min(len(s1), len(s2)) for c1, c2 in zip(s1, s2): if c1 != c2: diff += 1 diff += abs(len(s1) - len(s2)) return diff def main(): # 读取输入文件 with open('Lab_primers.tsv', 'r') as infile: lines = infile.readlines() # 解析数据(跳过表头) data = [] for line in lines[1:]: parts = line.strip().split() full_line = ' '.join(parts) idx2 = parts[1] idx4 = parts[3] data.append((full_line, idx2, idx4)) # 查找匹配对并写入输出 with open('primer_collision.txt', 'w') as outfile: n = len(data) for i in range(n): line1, idx2_i, idx4_i = data[i] for j in range(i + 1, n): line2, idx2_j, idx4_j = data[j] if count_diff(idx2_i, idx2_j) < 3 and count_diff(idx4_i, idx4_j) < 3: outfile.write(f"{line1}\n") outfile.write(f"{line2}\n") outfile.write("\n") if __name__ == "__main__": main()
运行命令
python collision.py
性能预期
这两种方案的运行时间都会从30+分钟缩短到几秒到几分钟,具体取决于你的硬件配置。核心优化点:
- 仅读取输入文件一次,所有数据存入内存
- 避免了百万级的外部进程调用
- 字符差异计算在进程内完成,无额外开销
内容的提问来源于stack exchange,提问作者bobia9193
相关产品推荐
相关产品推荐

