正则表达式:如何根据前一行匹配一行

时间:2018-02-24 13:02:49

标签: regex ctags

我有一个包含许多行的.pdb文件(分子坐标文件) 看起来像这些。

我有兴趣编写ctags选项,以便能够为这些文件格式生成标签,并使用Vim飞过它们。

SOMETHING      0.000000  0.021483  0.000000        0.00000                         
SOMETHING      0.000000  0.000000  0.008964        0.00000                         
ATOM      1 
ATOM      2 
ATOM      3 
ATOM      4 
ATOM      5 
SOMETHING      0.000000  0.021483  0.000000        0.00000                         
SOMETHING      0.000000  0.000000  0.008964        0.00000
ATOM      6 
ATOM      7 
...

所以我要为ATOM条目创建标签就是将.ctags编辑成:

--langdef=PDB
--langmap=PDB:.pub
--regex-pdb=/^ATOM/a,atom/

当然,结果是每个原子都有自己的标签。 我真正想要的是仅匹配同一关键字的第一次出现(或每次出现)。即标记ATOM关键字:

ATOM      1
ATOM      6 

我尝试过负面的回顾,但我错过了一些东西......

编辑: 使用(^[A-Z]+).*$\s(?!\1)https://regexr.com上测试正则表达式给出了一个可接受的结果,基本匹配每个相同关键字块的每个最后一次出现。 不幸的是,Universal ctags虽然支持--mline-regexp=但不支持回望/前瞻......

编辑 - 已解决:

感谢所有回复我帖子的人,我最终成功地实现了我想要的一些建议。 一个很好的工作解决方案是:

--mline-regex-PDB=/(^ATOM).*$[[:space:]](ATOM.*$[[:space:]])*/\1/a/{mgroup=1}{_advanceTo=2end}

它的作用如下:

  • (^ATOM)匹配行开头的ATOM字词
  • .*$以及整条线本身,无论它包含什么。
  • [[:space:]] POSIX字符类以匹配换行符
  • (ATOM.*$[[:space:]])*这基本上是:之后的所有行都以ATOM
  • 开头
  • /\1/a/标记名称将匹配组1(第一个ATOM匹配)和类似a
  • {mgroup=1}标记将指向第1组匹配的行
  • {_advanceTo=2end}重申第2组末尾的模式搜索(即以ATOM开头的一大块连续行,这就是魔法;)

2 个答案:

答案 0 :(得分:0)

更新:ctags是否支持条件语句?

^(ATOM\s+\d+\s*$)?(?(1)|.*\n+^(ATOM\s+\d+)\s*$)

regex101.com

上查看

尝试下一个正则表达式:

^(?!ATOM\s+\d+\s*).+$\n+^(ATOM\s+\d+)\s*$

答案 1 :(得分:0)

Universal-ctags(https://ctags.io)具有经验的多行正则表达式元解析器。

$ cat /tmp/foo.pdb 
cat /tmp/foo.pdb 
SOMETHING      0.000000  0.021483  0.000000        0.00000                         
SOMETHING      0.000000  0.000000  0.008964        0.00000                         
ATOM      1 
ATOM      2 
ATOM      3 
ATOM      4 
ATOM      5 
SOMETHING      0.000000  0.021483  0.000000        0.00000                         
SOMETHING      0.000000  0.000000  0.008964        0.00000
ATOM      6 
ATOM      7
SOMETHING      0.000000  0.021483  0.000000        0.00000                         
SOMETHING      0.000000  0.000000  0.008964        0.00000
ATOM      8
SOMETHING      0.000000  0.000000  0.008964        0.00000
ATOM      9
$ cat pdb.ctags
cat pdb.ctags
--langdef=PDB
--langmap=PDB:.pdb
--kinddef-PDB=a,atom,atoms
--mline-regex-PDB=/^ATOM[[:space:]]+(([[:digit:]]*)([[:space:]]+ATOM[[:space:]]+([[:digit:]]*))*)/\2/a/{mgroup=2}{_advanceTo=1end}
$ ./ctags --fields=+K -o - --options=pdb.ctags /tmp/foo.pdb 
1   /tmp/foo.pdb    /^ATOM      1 $/;"  atom
6   /tmp/foo.pdb    /^ATOM      6 $/;"  atom
8   /tmp/foo.pdb    /^ATOM      8$/;"   atom
9   /tmp/foo.pdb    /^ATOM      9$/;"   atom