vim-按逗号分隔行,并为每个标记添加前缀

vim-按逗号分隔行,并为每个标记添加前缀,vim,Vim,我有这样的台词: <prefix> <token1>, <token2>, .... <tokenN>; <prefix> <token1>; <prefix> <token2>; ... <prefix> <tokenN>; ; 其中,令牌的数量是可变的,每个令牌是一个字符或数字 我想在Vim中将它们拆分为以下内容: <prefix> <token1&

我有这样的台词:

<prefix> <token1>, <token2>, .... <tokenN>;
<prefix> <token1>;
<prefix> <token2>;
...
<prefix> <tokenN>;
其中,令牌的数量是可变的,每个令牌是一个字符或数字

我想在Vim中将它们拆分为以下内容:

<prefix> <token1>, <token2>, .... <tokenN>;
<prefix> <token1>;
<prefix> <token2>;
...
<prefix> <tokenN>;
;
;
...
;
我试着像这样抓住模式
/\s\+\(\w\+,\s*\){1,}\(\w\+\)/但我不确定如何提取可变数量的令牌(\1和\2仅给定令牌n-1和令牌n)


想法?提前谢谢。

我想

:substitute/, /;\r/g
将逗号更改为-换行符,然后使用某种形式的范围选择器(
:global
或可视模式,最有可能)执行此操作

其中,
^R
键入为Ctrl-VCtrl-R

说明:

0       go to the start of the row
daw     delete a word (and put in the default register)
:s/     substitute
, /       a comma and a space
;\r/      with a comma and a newline
g         on the whole line
:'`,.   on each line from the one we were before to this one
normal  execute as if in normal mode
I         insert at the start of the line
^R"       the content of the default register
甚至更短:

0yaw
:s/, /\=";\r".@"/g

如果前缀在任何地方都是固定的(您建议使用以
/\s\+…
开头的模式),那么您可能可以使用以下简单的方式:

:g/^<prefix>\s/s/,\s\+/;\r<prefix> /g
打破这种模式:

  • \(\S\+\)
    :匹配捕获组中的前缀。(您可以使用比非空白更好、更具体的方法来正确匹配您关心的行。)
  • \s\+
    :跳过空白
  • [^,]*
    :跳过第一个令牌
  • \zs
    :标记匹配的开始。替换只能替换此零件
  • \(,\s*[^,]*\)*
    :一个或多个标记的序列,前面有逗号和可选空格
  • \ze
    :标记比赛结束
  • $:匹配所有代码末尾的分号
此时,策略还是用分号、回车符和前缀替换逗号,但这样做是动态的

这是通过在替换中使用这些来实现的:

  • \=
    :在替换中使用表达式(请参阅。)
  • 替换(子匹配(0),“,\s*”,“;\r”.submatch(1)。”,“g”)
    :用分号、回车符和前缀以及空格序列替换逗号(以及其后的可选空格)
  • 子匹配(0)
    :我们正在对匹配执行此类替换(仅在
    \zs
    \ze
    之间)
  • “;\r”
    :替换的开始、分号和回车
  • :点运算符连接Vimscript中的字符串
  • 子匹配(1)
    :返回到捕获组1,我们在本例中使用它来捕获前缀
  • 'g'
    :替换所有匹配项
这是一个相当复杂的替换,但具有在单个
:s
命令中处理替换的优点,这使得在一个范围内使用它或以后重复它更容易,而无需记录宏


:s
替换中使用
substitute()
函数的技术对于处理捕获组不足的情况也很有用,例如您当前的捕获组。

您不需要控制-v控制-r;register recall在命令行上工作。@D.BenKnoble我知道,我不想把它放在命令行中,这是一个评估时间的问题。如果你只考虑一次,没关系。例如,如果将其放入映射中,“我的方式”将在每次执行时插入正确的寄存器值,则在创建映射时,您的方式将始终替换为寄存器的值。这不会将添加到newline@Slayer当然会的;这是两个步骤,第二个步骤添加前缀。虽然我可能会做一些很棒的酱汁!非常感谢。我应该在OP中提到,但是,是的,我的前缀是可变的。
:s/\(\S\+\)\s\+[^,]*\zs\(,\s*[^,]*\)*\ze;$/\=substitute(submatch(0),',\s*',";\r".submatch(1)." ",'g')/