如何从a的最后一个匹配到b进行搜索和替换?
How to search and replace from the last match of a until b?
我有一个乳胶文件,我想在其中删除 \end{quoting}
之前的最后一个 \
。
我正在处理的文件部分与此类似:
\myverse{some text \
some more text \}%
%
\myverse{again some text \
this is my last line \}%
\footnote{possibly some footnotes here}%
%
\end{quoting}
超过数百行,可能涵盖 50 个 quoting
环境。
我试过 :%s/\\}%\(\_.\{-}\)\end{quoting}/}%\end{quoting}/gc
但不幸的是 non-greedy
量词 \{-}
仍然太贪心了。
它从我的示例的第二行开始捕获,直到引用环境结束,我猜贪心量词会赶上文件中的最后一个 \end{quoting}
。有没有可能通过搜索和替换来做到这一点,或者我应该为此编写一个宏吗?
编辑:我的预期输出看起来像这样:
this is my last line }%
\footnote{possibly some footnotes here}%
%
\end{quoting}
(我应该补充一点,我现在已经通过编写一个小宏解决了这个任务,但我仍然很好奇它是否也可以通过搜索和替换来完成。)
你在使用非贪婪 multi 的正确轨道上。 Vim 帮助文件
说明,
"{-}" is the same as "*" but uses the shortest match first algorithm.
但是,下一行会警告您遇到的问题。
BUT: A match that starts earlier is preferred over a shorter match: "a{-}b" matches "aaab" in "xaaab".
据我所知,最好的解决方案是使用宏。
我 认为 您正在尝试从 end{quoting}
之前的 最后一次 匹配 \}%
, 直到 end{quoting}
, 在这种情况下你真的不想要 any 字符 (\_.
), 你想要 "any character that isn't \}%
" (是的我知道这不是一个单一的字符,但基本上就是这样。
所以,只需(哈!)更改您的模式以使用 \%(\%(\\}%\)\@!\_.\)\{-}
而不是 \_.\{-}
;这意味着该模式不能包含多个 \}%
序列,从而实现您的目标(据我所知)。
这使用负零宽度先行模式\@!
来确保下一个匹配任何字符, 仅限于不匹配我们想要避免的特定文本(但除此之外,任何 else 仍然匹配)。有关更多信息,请参阅 :help /zero-width。
即您的最终命令是:
:%s/\\}%\(\%(\%(\\}%\)\@!\_.\)\{-}\)\end{quoting}/}%\end{quoting}/g
(我注意到您的 "expected" 输出出于某种原因不包含前几行,它们只是被省略了还是命令应该删除它们?)
我有一个乳胶文件,我想在其中删除 \end{quoting}
之前的最后一个 \
。
我正在处理的文件部分与此类似:
\myverse{some text \
some more text \}%
%
\myverse{again some text \
this is my last line \}%
\footnote{possibly some footnotes here}%
%
\end{quoting}
超过数百行,可能涵盖 50 个 quoting
环境。
我试过 :%s/\\}%\(\_.\{-}\)\end{quoting}/}%\end{quoting}/gc
但不幸的是 non-greedy
量词 \{-}
仍然太贪心了。
它从我的示例的第二行开始捕获,直到引用环境结束,我猜贪心量词会赶上文件中的最后一个 \end{quoting}
。有没有可能通过搜索和替换来做到这一点,或者我应该为此编写一个宏吗?
编辑:我的预期输出看起来像这样:
this is my last line }%
\footnote{possibly some footnotes here}%
%
\end{quoting}
(我应该补充一点,我现在已经通过编写一个小宏解决了这个任务,但我仍然很好奇它是否也可以通过搜索和替换来完成。)
你在使用非贪婪 multi 的正确轨道上。 Vim 帮助文件 说明,
"{-}" is the same as "*" but uses the shortest match first algorithm.
但是,下一行会警告您遇到的问题。
BUT: A match that starts earlier is preferred over a shorter match: "a{-}b" matches "aaab" in "xaaab".
据我所知,最好的解决方案是使用宏。
我 认为 您正在尝试从 end{quoting}
之前的 最后一次 匹配 \}%
, 直到 end{quoting}
, 在这种情况下你真的不想要 any 字符 (\_.
), 你想要 "any character that isn't \}%
" (是的我知道这不是一个单一的字符,但基本上就是这样。
所以,只需(哈!)更改您的模式以使用 \%(\%(\\}%\)\@!\_.\)\{-}
而不是 \_.\{-}
;这意味着该模式不能包含多个 \}%
序列,从而实现您的目标(据我所知)。
这使用负零宽度先行模式\@!
来确保下一个匹配任何字符, 仅限于不匹配我们想要避免的特定文本(但除此之外,任何 else 仍然匹配)。有关更多信息,请参阅 :help /zero-width。
即您的最终命令是:
:%s/\\}%\(\%(\%(\\}%\)\@!\_.\)\{-}\)\end{quoting}/}%\end{quoting}/g
(我注意到您的 "expected" 输出出于某种原因不包含前几行,它们只是被省略了还是命令应该删除它们?)