如何用Python/Shell重排大原子文本文件中的行顺序?
解决XYZ文件原子行重排问题
针对你这个14万行的大型XYZ文件,我提供两种高效的分块处理方案,都能在不占用过多内存的前提下完成原子顺序调整:
Python解决方案
Python脚本的优势是可读性强、容易修改,适合后续调整需求。核心思路是逐块处理:每次只读取一个分子块(1行头+15行原子),调整原子顺序后再写入输出文件。
def reorder_atom_blocks(input_file, output_file): with open(input_file, 'r') as f_in, open(output_file, 'w') as f_out: while True: # 读取块头行(包含原子数量和文件路径) header = f_in.readline() if not header: break # 文件处理完毕 # 提取当前块的原子数量(这里固定为15,代码兼容其他数量的块) try: num_atoms = int(header.strip().split()[0]) except ValueError: # 如果不是有效块头,直接写入跳过 f_out.write(header) continue # 读取当前块的所有原子行 atoms = [] for _ in range(num_atoms): line = f_in.readline() if not line: break # 文件提前结束,处理已读取内容 atoms.append(line) # 确保读取到完整的原子行 if len(atoms) != num_atoms: f_out.write(header) f_out.writelines(atoms) break # 按照目标顺序重新排列原子行 # 原顺序分组:[C,H,H,S], [C,H,H,S], [C,H,H,S], [H,H,H] # 目标顺序:[C,S,H,H,H], [C,S,H,H,H], [C,S,H,H,H] reordered = [ # 第一组 atoms[0], atoms[3], atoms[1], atoms[2], atoms[12], # 第二组 atoms[4], atoms[7], atoms[5], atoms[6], atoms[13], # 第三组 atoms[8], atoms[11], atoms[9], atoms[10], atoms[14] ] # 写入处理后的块 f_out.write(header) f_out.writelines(reordered) # 调用示例:替换为你的输入输出文件路径 reorder_atom_blocks('your_input.xyz', 'your_output.xyz')
Shell awk解决方案
如果你习惯用Shell工具,awk脚本处理大文件的速度更快,且不需要Python环境。同样是分块处理逻辑:
- 把下面的代码保存为
reorder_atoms.awk:
BEGIN { in_block = 0 num_atoms = 0 } # 匹配块头行(以数字开头) /^[0-9]+/ { if (in_block) { # 处理上一个块的原子排列 print atoms[0] print atoms[3] print atoms[1] print atoms[2] print atoms[12] print atoms[4] print atoms[7] print atoms[5] print atoms[6] print atoms[13] print atoms[8] print atoms[11] print atoms[9] print atoms[10] print atoms[14] delete atoms in_block = 0 } # 打印当前块头 print $0 num_atoms = $1 in_block = 1 idx = 0 next } # 收集原子行 in_block { atoms[idx++] = $0 if (idx == num_atoms) { # 处理当前块的原子排列 print atoms[0] print atoms[3] print atoms[1] print atoms[2] print atoms[12] print atoms[4] print atoms[7] print atoms[5] print atoms[6] print atoms[13] print atoms[8] print atoms[11] print atoms[9] print atoms[10] print atoms[14] delete atoms in_block = 0 } } # 处理文件末尾的最后一个块 END { if (in_block && idx == num_atoms) { print atoms[0] print atoms[3] print atoms[1] print atoms[2] print atoms[12] print atoms[4] print atoms[7] print atoms[5] print atoms[6] print atoms[13] print atoms[8] print atoms[11] print atoms[9] print atoms[10] print atoms[14] } }
- 在终端运行命令:
awk -f reorder_atoms.awk your_input.xyz > your_output.xyz
关键注意事项
- 测试先行:建议先截取一小段测试数据运行脚本,确认输出符合预期后再处理整个14万行的文件。
- 兼容性:两种方案都假设所有块的原子数量都是15,如果文件中有其他数量的块,Python脚本会原样输出,awk脚本可能需要调整逻辑。
- 内存效率:都是逐块读取处理,不会一次性加载整个文件到内存,适合大型文件。
内容的提问来源于stack exchange,提问作者TYSH
相关产品推荐
相关产品推荐

