用Bash替换FASTA文件指定位置数字为对应索引的序列名
替换FASTA文件读名中的索引数字为对应序列名
场景说明
- FASTA文件格式:目标文件夹内的FASTA文件中,以
>开头的行是序列读名,下一行对应DNA序列,读名格式示例:> 887_ENCFF899MTI.fastq.gz_seq1 GGCCCGCCTCCCGTCGGCCGGTGCGAGCGGCTCCGCGA > 55_ENCFF899MTI.fastq.gz_seq2 GGGGGGGGCGTCTCGCGCAAACGTCCATAAC - SequenceNames.txt格式:每行存储一个序列名,行号与FASTA读名中
>和第一个_之间的数字索引一一对应(例如数字1对应文件第一行的SequenceA):SequenceA SequenceB ...
需求
仅替换FASTA读名中>与第一个_之间的数字为SequenceNames.txt中对应行号的序列名,不修改文件名里的数字。示例效果:
原内容:
> 1_ENCFF899MTI.fastq.gz_seq1 ACTATC > 2_ENCFF899MTI.fastq.gz_seq1
替换后:
> SequenceA_ENCFF899MTI.fastq.gz_seq1 ACTATC > SequenceB_ENCFF899MTI.fastq.gz_seq1
尝试过的无效命令
使用gawk时因数组索引匹配逻辑错误未得到预期结果,尝试的命令:
gawk '{print gensub(/^> ([0-9]*)_/,array[pattern],"\1")}'
Bash解决方案
方法1:单文件处理(awk实现,推荐)
先将SequenceNames.txt的内容加载到数组,再遍历FASTA文件匹配替换:
awk ' BEGIN { # 加载SequenceNames.txt到数组,行号作为索引(awk数组默认从1开始,刚好匹配需求) while ((getline name < "SequenceNames.txt") > 0) { seq_names[NR] = name } close("SequenceNames.txt") } # 处理以>开头的读名行 /^> / { # 捕获>和第一个_之间的数字 match($0, /^> ([0-9]+)_/, parts) if (parts[1] in seq_names) { # 替换数字为对应序列名,保留后续内容 $0 = "> " seq_names[parts[1]] substr($0, RSTART+RLENGTH) } } # 输出所有行(包括未修改的序列行) 1' your_fasta_file.fasta > output.fasta
方法2:批量处理文件夹内所有FASTA文件
结合find遍历文件,替换后覆盖原文件(建议先备份):
find /path/to/your/fasta_folder -name "*.fasta" -type f | while read -r file; do awk ' BEGIN { while ((getline name < "SequenceNames.txt") > 0) { seq_names[NR] = name } close("SequenceNames.txt") } /^> / { match($0, /^> ([0-9]+)_/, parts) if (parts[1] in seq_names) { $0 = "> " seq_names[parts[1]] substr($0, RSTART+RLENGTH) } } 1' "$file" > "$file.tmp" && mv "$file.tmp" "$file" done
注意事项
- 确保
SequenceNames.txt的行号与FASTA读名中的数字严格对应 - 如果数字超出
SequenceNames.txt的行数,该行会保持原内容不替换 - 批量处理前建议手动备份部分文件,避免意外修改
内容的提问来源于stack exchange,提问作者jelfman
相关产品推荐
相关产品推荐

