Regex Vim正则表达式:覆盖回引用?

Regex Vim正则表达式:覆盖回引用?,regex,parsing,vim,csv,backreference,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

项目:

以维基百科的罗马执政官名单为例,将数据放在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}
因此,本质上:

  • 在年初查找年份(或表示萨福克执政官):
    (\d+| suff\)
  • 下一个分组(我们称之为外部组)最多需要找到两次:
    (外部组){,2}
  • 对于这两个外部组,请分别查找:
  • Praenomen,带可选句点(有时不存在):
    (\w+。=)
  • 名称:
    (\w+)
  • 可选cognomen(包括空格,如下所示):
    (\s\w+)=
  • 可选名称:
    (\s\w+)=
  • 可选迭代(表示他第n次担任执政官)。数据源的迭代次数不超过8次(因此I和V就足够了):
    (\s[iv]+)=
  • 可选的解释性注释,如“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 regex(或任何兼容的regex):如果外部组被迭代,如何引用组(组内)?

    是的,在重复中捕获组会被覆盖到最新的匹配值。根据链接页面底部附近的部分:

    正则表达式引擎不会永久替换正则表达式中的反向引用。每次需要使用时,它都将使用保存到反向引用中的最后一个匹配项。如果通过捕获括号找到新的匹配项,则会覆盖以前保存的匹配项

    您必须明确写出一定数量的捕获组

    我并不特别熟悉vim的正则表达式引擎,因此这里有一个简单的示例。
    假设您的文本是abc 12 345 6789 xyz

    # with repetition
    /^\w+( \d+){1,3} \w+$/
    
    # yields:
    # 0: abc 12 345 6789 xyz
    # 1:  6789
    
    # -----
    # writing out each subpattern
    /^\w+( \d+)( \d+)?( \d+)? \w+$/
    
    # yields:
    # 0: abc 12 345 6789 xyz
    # 1:  12
    # 2:  345
    # 3:  6789
    

    请注意,由于重复范围为
    {1,3}
    ,我将第二个和第三个
    (\d+
    )设置为可选的
    ,我将其分解为子步骤,使用vim函数,而不是使用所有
    正常的
    (双关语)方式:

    看到我做了什么吗?让事情变得简单明了

    Edit稍微减少懒惰,让我们定义一个helper函数,将其拆分为至少3个子字符串,并将它们分开:

    function! Consul(s)        
        return join((split(a:s) + ["","",""])[0:2], "\t")
    endf
    
    现在将替换减少为(仅限SO的换行符)

    在你的输入上运行这种美会产生

    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}
    

    缺少链接:消除了一个bug并添加了一个步骤来完成解决方案哇,我从未见过这些join和submatch命令。如果有机会,我会尝试一下。
    split
    命令在concur函数中做什么?我只知道split命令会打开一个新窗口;如何将其与join命令结合起来?这是函数,而不是函数。另请参见,嗯。我想迭代外部组的一个原因是因为Vim告诉我“太多了”。“否则我可能会做得太懒,然后把整个组写两遍。”I+1这是解释的答案
    :%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}