2

我有这个问题:

输入文本:

this is my text text text and more text
this is my text myspace this is my text
this space is my text space this is my
this is my text this is my text
this space is my text space space myspace

假设我想搜索“空间”
,我想将其作为输出:

this is my text text text and more text
space
space space
this is my text this is my text
space space space space

同一行上的匹配项必须用空格分隔。
没有匹配的行必须保持原样。

所有其他搜索项相同。

今天下午我试图实现这一点,但没有成功。
谁能帮我?

4

3 回答 3

3

这条棘手的线路适合你吗?

:g/space/s/space/^G/g|s/[^^G]//g|s/^G/space /g

^G以上你需要按Ctrl-V Ctrl-G

上述命令的输出与您的示例相同,除了模式后的结尾空格(本例中为空格)。但它很容易修复,例如在线路s/ $//之后链接另一个。:g

于 2013-07-05T20:46:31.913 回答
3

解决方案:

:g/space/s/\(.*space\).*$/\1/|s/.\{-}space/ space/g|s/^ //

解释:

这很棘手,但可以做到。但是,它不能用一个正则表达式来完成。

我们要做的第一件事是在最后一场比赛之后摆脱任何东西(我们实际上利用了正则表达式在此处默认为贪婪的事实):

s/\(.*space\).*$/\1/

然后我们删除所有内部匹配之间的任何内容(注意我们使用*这里的惰性版本,\{-}):

s/.\{-}space/ space/g

上一步将在结果中留下一个初始空间,所以我们去掉它:

s/^ //

幸运的是,在 vim 中,我们可以将替换与|字符链接在一起。所以,把它们放在一起:

:g/space/s/\(.*space\).*$/\1/|s/.\{-}space/ space/g|s/^ //
于 2013-07-05T20:52:57.943 回答
0

Kent 的解决方案使用了一个很好的技巧,使其仅适用于固定字符串,但它简洁而简短。Ethan Brown 的答案更笼统,但也增加了三个步骤的复杂性。我认为可以根据这个非常相似的问题中接受的答案来开发最佳解决方案。

与 Ethan Brown 的假设相反,这确实可以通过一个正则表达式替换来完成。在这里,它的所有丑陋:

:g/space/s/\%(^\|\%(space \)*space\%( \%(.*space\)\@=\)\?\)\zs\%(\%(space \)*space\%( \%(.*space\)\@=\)\?\)\@!.\{-1,}\ze\%(\%(space \)*space\%( \%(.*space\)\@=\)\?\|$\)//g

当您使用我的PatternsOnText 插件:DeleteExcept中的命令时,它变得更具可读性:

:g/space/DeleteExcept/\%(space \)*space\%( \%(.*space\)\@=\)\?/

解释

这会删除所有内容,除了

  • 潜在的多次连续发生\%(space \)*
  • 这个词的space
  • 当它不是该行中的最后一个匹配时,包括尾随空格,即有一个后续匹配\%(.*space\)\@=,因此空格不会被吞下
  • \?或在该行的最后一个匹配项之后排除(即删除)它。

更实用的选择

尽管提出上述解决方案是一个很好的挑战,但在实践中,我也倾向于采用两步法,因为它更简单:

:g/space/DeleteExcept/space\%( \|$\)/

这留下了可以修剪的尾随空格

:%s/ $//
于 2013-07-06T09:45:32.017 回答