gVim 使用正则表达式在每个匹配模式之前插入序列号

gVim insert serial number before each matched pattern using regex

我在 Windows 上使用 gVim。我有一个 XML 文件,其内容(已提取)如下:

      <ExtendedAttributes />
    </Activity>
    <Activity Id="ded54c70-1ef4-4aeb-852e-3740882c36ff" Name="Activity 1">
      <Performers>
        <Performer>2212646c-2674-4329-9ddc-1f8376e952e1</Performer>
      </Performers>
    </Activity>
    <Activity Id="cf70ec72-4d49-434a-abf3-aa3e8dc000b5" Name="Activity 2">
      <Description>This is a dummy description</Description>
      <Implementation>
        <Task />

我想在每个 activity 的名称前添加一个 ID,即

<Activity Id="ded54c70-1ef4-4aeb-852e-3740882c36ff" Name="Activity 1">

会变成

<Activity Id="ded54c70-1ef4-4aeb-852e-3740882c36ff" Name="10 Activity 1">

<Activity Id="cf70ec72-4d49-434a-abf3-aa3e8dc000b5" Name="Activity 2">

会变成

<Activity Id="cf70ec72-4d49-434a-abf3-aa3e8dc000b5" Name="20 Activity 2">

等等。我试过 \(<Activity Id="[0-9a-f-]*" Name="\)\@<=[A-Za-z ,]\+ 可以得到 "Name" 属性的值。但是当我尝试使用 http://vim.wikia.com/wiki/Making_a_list_of_numbers 中提到的命令 :let i=0 | g/.... | let i=i+1 时,我永远无法让它工作。我所能做的就是用序列号替换名称(而我想要 [序列号] [名称] )

任何人都可以解释一下吗?
非常感谢你。

奥利弗

[编辑]

我尝试了以下方法:

:let @a=1 | %s/\(<Activity Id="[0-9a-f-]*" Name="\)\@<=\([A-Za-z() ,&?;/]\+\)/\=(@a+setreg('a',@a+1))/g

但它只用数字替换了名字,

:let @a=1 | %s/\(<Activity Id="[0-9a-f-]*" Name="\)\@<=\([A-Za-z() ,&?;/]\+\)/\=(@a+setreg('a',@a+1))./g

但我得到 "invalid expression",

:let @a=1 | %s/\(<Activity Id="[0-9a-f-]*" Name="\)\@<=\([A-Za-z() ,&?;/]\+\)/\=(@a+setreg('a',@a+1)).' './g

但我得到 "invalid expression",

:let @a=1 | %s/\(<Activity Id="[0-9a-f-]*" Name="\)\@<=\([A-Za-z() ,&?;/]\+\)/\=join((@a+setreg('a',@a+1)),' ',)/g

但我得到 "invalid argument for join()",

:let @a=1 | %s/\(<Activity Id="[0-9a-f-]*" Name="\)\@<=\([A-Za-z() ,&?;/]\+\)/\=(@a+setreg('a',@a+1))+/g

但我得到 "invalid expression"。

假设您想要的 ID 是 Activity 后面的数字乘以 10(这是我从您的示例中了解到的),这可以通过以下方式完成:

:%s/Activity \(\d\+\)/\=submatch(1) * 10 . " " . submatch(0)

故障…

  • 对每一行执行替换:

    :%s/...
    
  • 搜索 Activity,然后搜索 space,然后搜索一个或多个数字,捕获数字:

    .../Activity \(\d\+\)/...
    
  • 在 "sub-replace expression":

    中使用捕获的数字和整个匹配
    .../\=submatch(1)*10 . " " . submatch(0)
    

    我们用 10、space 和整个匹配连接捕获的数字。

    :help sub-replace

我终于找到了分两步完成任务的方法:

1)通过命令插入一个不太可能出现在内容中的静态字符串(例如##%%##%%):

:%s/\(<Activity Id="[0-9a-f-]*" Name="\)\@<=\([A-Za-z() ,&?;/]\+\)/##%%##%% /g

2) 用数字序列替换静态字符串:

:let @a=1 | %s/##%%##%%/\=(@a+setreg('a',@a+1))/g

这确实不是一个完美的解决方案。欢迎任何仅 1 步的解决方案。非常感谢你。

这个仅在行尾的 Activity 处发生变化。 首先,我们尝试单独搜索

/Name="\zs[^"]*\ze"

那就问问我们亲爱的vim

let @a=10 | %s//\=(@a+setreg('a', @a+10)) . " " . submatch(0)