You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Vi中批量删除PDB文件重复坐标原子行(无需手动确认)

在Vi/Vim或Emacs中批量去重PDB文件的重复坐标原子行

问题场景

我正在处理一个PDB文件,该文件包含大量原子及其坐标,示例行如下:

ATOM      1  ZN  ZN2 Z   1       6.703   3.973  -2.488  1.00  0.00      ZINC
ATOM      2  ZN  ZN2 Z   1      -2.639   3.973  -2.488  1.00  0.00      ZINC

文件中存在重复坐标的原子:三组坐标值重复出现,但每行的原子编号不同,导致整行不完全相同。希望保留每组重复坐标的一行,删除其余行,不关注顺序。目前采用手动搜索替换坐标为@@@再删除的方式:

:%s/6.703   3.973  -2.488/@@@/gc
:g/@@@/d

但文件过长,手动操作耗时易出错,求更简便的方法,优先Vi编辑器,Emacs也可。


Vi/Vim 解决方案

方法1:结合系统sort+uniq命令(快速高效)

利用外部命令按坐标排序后去重,适合大文件:

  1. 按坐标字段(第7-9列,空格分隔)排序:
    :%!sort -k7,9
    
  2. 跳过前6个字段(原子编号等不重复内容),只比较后续内容去重,保留每组重复的第一行:
    :%!uniq -f6
    

注:如果需要保留原始顺序,不推荐此方法;若对顺序无要求,这是最快的方式。

方法2:Vim内置脚本(保留原始顺序)

通过字典记录已出现的坐标,遍历文件删除重复行,不改变原有行的顺序:
在Vim命令行执行:

:let seen = {}
:g/^ATOM/let coords = split(getline('.'))[6:8] | let key = join(coords, ' ') | if has_key(seen, key) | delete() | else | let seen[key] = 1 | endif
  • let seen = {}:创建空字典存储已出现的坐标
  • :g/^ATOM/:对所有以ATOM开头的原子行执行后续逻辑
  • split(getline('.'))[6:8]:拆分当前行为字段列表,提取第7-9个元素(坐标部分)
  • 若坐标已在字典中则删除当前行,否则将坐标存入字典标记为已出现

Emacs 解决方案

方法1:调用外部sort+uniq命令

  1. 选中整个文件(C-x h)
  2. 执行 M-x shell-command-on-region
  3. 输入命令 sort -k7,9 | uniq -f6,回车后确认替换原内容即可

方法2:Elisp脚本(保留原始顺序)

在Emacs中执行以下脚本(可通过M-x eval-expression逐行执行,或写入临时脚本):

(let ((seen (make-hash-table :test 'equal)))
  (goto-char (point-min))
  (while (not (eobp))
    (let* ((line (buffer-substring-no-properties (line-beginning-position) (line-end-position)))
           (fields (split-string line))
           (coords (subseq fields 6 9))
           (key (string-join coords " ")))
      (if (gethash key seen)
          (kill-whole-line)
        (puthash key t seen)))
    (forward-line 1)))
  • 创建哈希表seen记录已出现的坐标
  • 从文件开头遍历每一行,提取坐标字段作为键
  • 若坐标已存在则删除当前行,否则将坐标存入哈希表

内容的提问来源于stack exchange,提问作者user19619903

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 23:36:21