regex - Vim 正则表达式 : overwritten back references?

标签 regex parsing vim csv backreference

项目:

获取维基百科的罗马执政官列表,将数据放入 CSV 文件中,这样我就可以制作一张关于领事权方面各氏族兴衰的图表

示例数据源:

509,L. Iunius Brutus,L. Tarquinius Collatinus
suff.,Sp. Lucretius Tricipitinus,P. Valerius Poplicola
suff.,M. Horatius Pulvillus,
508,P. Valerius Poplicola II,T. Lucretius Tricipitinus
507,P. Valerius Poplicola III,M. Horatius Pulvillus II

Vim 搜索:

/\v(\d+|suff\.),((\w+\.=) (\w+)(\s\w+)=(\s\w+)=(\s[iv]+)=(\s\(.{-}\))=,=){,2}

本质上:

  1. 在开头查找年份(或 suffect consul 的指示):(\d+|suff\.)
  2. 下一个分组(我们称它为外部组)最多需要找到两次:(outer group){,2}
  3. 对于这两个外部组中的每一个,找到:
    1. Praenomen,带有可选句点(有时不存在):(\w+.=)
    2. 名称:(\w+)
    3. 可选的代号(包括空格,如下所示):(\s\w+)=
    4. 可选的 agnomen:(\s\w+)=
    5. 可选迭代(表示他第 n 次担任领事)。数据源没有超过 8 次迭代(因此 I 和 V 就足够了):(\s[iv]+)=
    6. 可选的解释性注释,例如“Sicinius (Sabinus?)”:(\s\(.{-}\))=

(最后一个逗号是可选的,因为它是行的末尾。)

所以反向引用结果是:

\1: year or suffect
\2: the entire second outer group
\3: Praenomen of second outer group (same with all below)
\4: Nomen
\5: Cognomen
\6: Agnomen
\7: Iteration
\8: Explanatory note

问题是我不知道如何捕获第一个外部组。这就像\2 和\3-\8 引用在看到第二个外部组时被覆盖。

使用这个替换:

:%s//1:{\1}^I2:{\2}^I3:{\3}^I4:{\4}^I5:{\5}^I6:{\6}^I7:{\7}^I8:{\8}^I9:{\9} 

我得到这个输出:

1:{509} 2:{L. Tarquinius Collatinus}    3:{L.}  4:{Tarquinius}  5:{ Collatinus} 6:{}    7:{}    8:{}    9:{}
1:{suff.}   2:{P. Valerius Poplicola}   3:{P.}  4:{Valerius}    5:{ Poplicola}  6:{}    7:{}    8:{}    9:{}
1:{suff.}   2:{M. Horatius Pulvillus,}  3:{M.}  4:{Horatius}    5:{ Pulvillus}  6:{}    7:{}    8:{}    9:{}
1:{508} 2:{T. Lucretius Tricipitinus}   3:{T.}  4:{Lucretius}   5:{ Tricipitinus}   6:{ II} 7:{}    8:{}    9:{}
1:{507} 2:{M. Horatius Pulvillus II}    3:{M.}  4:{Horatius}    5:{ Pulvillus}  6:{ II} 7:{}    8:{}    9:{}

我无法访问第一个外部组中的那些组。我认为它们正在被覆盖:它们正在被覆盖吗?如果是这样,有没有办法解决这个问题?

编辑: 原标题 Vim 正则表达式(或任何兼容的正则表达式):如果迭代外部组,如何引用组(组内)?

最佳答案

我会把它分解成子步骤,使用 vim 函数而不是用正常(双关语)方式来完成:

/\v(.{-}),(.{-}),(.*)

看到我做了什么吗?使事情变得更加简单和清晰

编辑 稍微不那么懒了,让我们定义一个辅助函数来拆分成至少 3 个子字符串并用制表符分隔它们:

function! Consul(s)        
    return join((split(a:s) + ["","",""])[0:2], "\t")
endf

现在将替换减少到(仅用于 SO 的换行符)

%s/\v(.{-}),(.{-}),(.*)/\=join(
  [submatch(1), Consul(submatch(2)), Consul(submatch(3))], "\t")/g

在您的输入 yield 上运行这种美丽

509 L.  Iunius  Brutus  L.  Tarquinius  Collatinus
suff.   Sp. Lucretius   Tricipitinus    P.  Valerius    Poplicola
suff.   M.  Horatius    Pulvillus           
508 P.  Valerius    Poplicola   T.  Lucretius   Tricipitinus
507 P.  Valerius    Poplicola   M.  Horatius    Pulvillus

我敢肯定这将是一个非常简单的步骤,可以根据您的喜好进一步装饰现在整齐地用制表符分隔的列。我可能会添加它,但现在,这是我能想到的最简单的事情:

:%s/\v(.{-})\t(.{-})\t(.{-})\t(.{-})\t(.{-})\t(.{-})\t(.{-})$/1:{\1}\t2:{\2}\t3:{\3}\t4:{\4}\t5:{\5}\t6:{\6}\t7:{\7}/g

结果:

1:{509} 2:{L.}  3:{Iunius}  4:{Brutus}  5:{L.}  6:{Tarquinius}  7:{Collatinus}
1:{suff.}   2:{Sp.} 3:{Lucretius}   4:{Tricipitinus}    5:{P.}  6:{Valerius}    7:{Poplicola}
1:{suff.}   2:{M.}  3:{Horatius}    4:{Pulvillus}   5:{}    6:{}    7:{}
1:{508} 2:{P.}  3:{Valerius}    4:{Poplicola}   5:{T.}  6:{Lucretius}   7:{Tricipitinus}
1:{507} 2:{P.}  3:{Valerius}    4:{Poplicola}   5:{M.}  6:{Horatius}    7:{Pulvillus}

关于regex - Vim 正则表达式 : overwritten back references?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9200982/

相关文章:

c# - word.otherword 的正则表达式

regex - 组的 gst 正则表达式不匹配会生成异常

javascript - 将内容从 Excel 粘贴到 Chrome

mysql - 在 SQL 中查询 JSON 字符串

java - Java 中的 MySQL 模式解析器?

html - vim 中正则表达式的问题

regex - Lazarus Pascal 或 Delphi - 转义字符以确保安全/完整性

jquery - JSON.parse() 期间 JSON 中出现意外标记

vim - VIM如何在巨大的源树的几个子树中导航

macos - 通过brew安装后如何在Mac OS上使用Vim 7.4?