【问题标题】:How to substitute for matching delimiters in vi?如何替换 vi 中的匹配分隔符?
【发布时间】:2011-11-18 05:29:18
【问题描述】:

我有一些匹配分隔符的文本(在这种情况下是花括号,而文本恰好是 LaTeX,这只是偶然的):

\nb{\vec{n},\vec{y}} \in \vec{z}

我想做的是将\nb{...} 全局替换为(...),同时尊重分隔符的嵌套。即,结果应该是

(\vec{n},\vec{y}) \in \vec{z}

而不是

(\vec{n},\vec{y}} \in \vec{z)

这是:%s/\\nb{\(.*\)}/(\1)/g 将产生的内容。标准正则表达式无法处理匹配的分隔符,所以我没想到这种方式会起作用。我可以使用一些特定于 vi 的技巧吗?

【问题讨论】:

    标签: vim vi replace delimiter


    【解决方案1】:

    如果您安装了surround.vim,那么以下应该可以解决问题

    :set nowrapscan
    :let @q="/\\m\\\\nb{/e+1\<cr>cs{)dF\\@q"
    gg@q
    

    如果你不这样做:

    :set nowrapscan
    let @q="/\\m\\\\nb{<cr>dt{yi{\"_ca{()\<esc>\"0P@q"
    gg@q
    

    概览

    创建一个搜索\nb{ 的递归宏,将光标定位在{ 内,将}{ 替换为()

    细节的荣耀

    • :set nowrapscan 这可以防止搜索在文件周围循环。
    • :let @q="..." 将我们的宏存储在 q 寄存器中
    • /\m\nb{/e+1 搜索 \nb{ 并将光标定位在 { 之后
    • cs{) 环绕版本只会将周围的{ 更改为)
    • @q 再次运行宏
    • 使用了",所以必须转义一些东西才能正常工作。
    • gg@q 转到文件顶部并执行寄存器q 中的宏

    这里的非环绕版本略有不同

    • yi{复制{里面的文字
    • "_ca{()&lt;esc&gt; 更改里面的文本,包括 {'s 并替换为 ()
    • "0P 将我们刚刚复制的内容粘贴到 ()

    【讨论】:

    • 非常好的帖子。尚未对其进行测试,但使用环绕.vim 的方法与我立即想到的方法相同。 +1
    • @Peter, @sehe:使用:global 命令重复更改有时会使整个事情变得不那么冗长。
    • @ib:当然可以,但我不知道乳胶,也不知道每行是否会有多个\nb{
    • @Peter:同意。无论如何,如果行中有多个\nbs,我宁愿重复一个较短的全局命令。 :-)
    • @ib:虽然我心里对递归宏有一个特殊的位置,但我必须同意你的观点,多个:g// 可能会更好。 :)
    【解决方案2】:

    我会使用以下:global 命令。

    :g/\\nb{/norm!/^M%r)[{r(dF\\
    

    键入^MCtrl+VEnter

    【讨论】:

    • 这会删除\nb 之前的行上的每个字,这是不正确的。看起来dB 应该是d2bdF\\
    • @uckelman:你说得对,我在最后一刻犯了一个错误。最初(从修订历史中可以看出),删除命令是d3h,但我决定最好不要根据命令的长度进行删除(可以在:g 中轻松更改)模式),我选择了简单的dB,当\nb之前有一个文本块时删除太多。
    • +1 用于使用 :g//[{。环绕声版本有点像:g/\\nb{/norm/^Mdt{cs{)。注意::norm上没有!
    猜你喜欢
    • 1970-01-01
    • 2021-03-11
    • 2013-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-07
    • 2020-05-03
    相关资源
    最近更新 更多