我的文件看起来像
{\o H}{\o e}{\o l}{\o l}{\o o} {\o W}{\o o}{\o r}{\o l}{\o d}
我想让文字看起来像这样
{\o Hello} {\o World}
我可以使用多种工具来解决这个问题,但我正在尝试使用vim替换。到目前为止,我有
:%s/{\\o \(.\{-}\)}{\\o \(.\{-}\)}/{\\o \1\2}/g
这里的模式是
.\{-}
匹配一些字符,非贪婪
{\\o .\{-}}
与正则表达式字符串{\o .*}
匹配,但与.*
和\( ... \)
创建用于反向引用的捕获组。
当我进行一次替换时,我得到了
{\o He}{\o ll}{\o o} {\o Wo}{\o rl}{\o d}
我可以再次运行此命令两次以获取
{\o Hell}{\o o} {\o Worl}{\o d}
然后
{\o Hello} {\o World}
但我真的很喜欢,如果有一种方法可以用一个命令来做这件事,即告诉vim替换继续传递文件,直到没有更多的匹配。在我看来,这应该是可能的。
有谁知道我需要添加什么魔法才能实现这一目标?它看起来不像有一个标志可以实现这一点。也许我不知道标签的一些技巧?
答案 0 :(得分:5)
您可以使用子替换表达式\=
在:s
的替换部分内执行第二次替换
:%s/\({\\o \S}\)\+/\='{\o '.substitute(submatch(0), '{\\o \(\S\)}', '\1', 'g').'}'/g
基本思想是捕获“单词”,例如{\o H}{\o e}{\o l}{\o l}{\o o}
,然后对捕获的“单词”submatch(0)
进行第二次替换。第二次替换将通过{\o
删除起始}
和尾随substitute(submatch(0), '{\\o \(\S\)}', '\1', 'g')
。这只留下了这个例子中的字母Hello
。从单词中提取每个字母后,我们会在起始{\o
和尾随}
中添加。
如需更多帮助,请参阅:
:h :s
:h sub-replace-expresion
:h substitute(
:h submatch(
:h literal-string
:h /\S
您还可以使用2个单独的替换。一个用于删除所有{\o
和}
。另一个替换会将它们重新添加回来,但这次是逐字的。
:%s/{\\o \(.\)}/\1/g
:%s/\S+/{\\o &}/g
这可以说是一种更简单的方法,假设您没有将此文本与其他不应采用此格式的文本混合在一起。
您也可以使用|
:
:%s/{\\o \(.\)}/\1/g|%s/\S+/{\\o &}/g
答案 1 :(得分:5)
这是一个更简单的解决方案:
递归宏。递归宏的基本思想是在发生错误之前调用自身的宏。当您运行替换命令并且没有匹配项时,这将引发错误。所以这是你需要做的基本布局。
清除宏' q'。这是必不可少的,因此在第一次运行时它不会做任何奇怪的事情。您可以使用
执行此操作qqq
或
:let @q=""
任何一个都有效。
开始录制。这只是:
qq
运行您的替换命令,然后调用宏。这将是
:%s/{\\o \(.\{-}\)}{\\o \(.\{-}\)}/{\\o \1\2}/g<cr>@q
由于@q
是运行宏的命令。 当您录制时,这不会做任何事情,因为您已经清除了注册&#39; q&#39;。最后,
停止录制,然后调用宏。
q@q
这将循环你刚刚按下的按键组,直到没有匹配。
把这一切放在一起:
qqqqq:%s/{\\o \(.\{-}\)}{\\o \(.\{-}\)}/{\\o \1\2}/g<cr>@qq@q
开头的5&#39; q。你也可以分配寄存器&#39; q&#39;从命令行,使用:
:let @q=':%s/{\\o \(.\{-}\)}{\\o \(.\{-}\)}/{\\o \1\2}/g<cr>@q'
然后点击
<cr>@q
作为旁注,我强烈推荐dedicated vim-site。