vim正则表达式只用一个空格替换多个连续的空格

jed*_*der 65 regex vim

我经常处理具有可变数量的空格的文本文件作为单词分隔符(像Word这样的文本处理器这样做,由于某些字体中不同大小的字母而公平地分配空白量,并且即使在保存为纯文本).

我想自动化用单个空格替换这些具有可变长度的空格序列的过程.我怀疑一个正则表达式可以做到这一点,但是在段落的开头还有空格(通常是四个,但并不总是),我想让它保持不变,所以基本上我的正则表达式也应该不触及前导空格这个增加了复杂性.

我正在使用vim,所以vim正则表达式方言中的正则表达式对我来说非常有用,如果这是可行的话.

我目前的进展如下:

:%s/ \+/ /g
Run Code Online (Sandbox Code Playgroud)

但它无法正常工作.

我也在考虑编写一个可以逐个解析文本行的vim脚本,按char处理每一行char并在第一行之后跳过空格,但我觉得这有点矫枉过正.

mik*_*obi 112

这将取代2个或更多空格

s/ \{2,}/ /g
Run Code Online (Sandbox Code Playgroud)

或者您可以在\+版本之前添加额外的空间

s/  \+/ /g
Run Code Online (Sandbox Code Playgroud)

  • 我认为这可能是最好最简单的答案.它还具有使用其他RegEx方言的额外好处! (9认同)
  • “也不应该触及前导空格”是这个答案似乎无法满足的要求。 (3认同)

Ari*_*zis 60

这样就可以了:

%s![^ ]\zs  \+! !g
Run Code Online (Sandbox Code Playgroud)

通过使用\zs\ze元序列,可以在Vim中比使用其他正则表达方言更容易地进行许多替换.他们所做的是从最终结果中排除部分匹配,即序列之前的部分(\zs"s"表示"从这里开始")或部分之后(\ze,"e"表示"结束此处").在这种情况下,模式必须匹配一个非空格字符first([^ ]),但以下\zs表示最终匹配结果(将被替换的内容)该字符之后开始.

由于无法在行前导空格前面有一个非空格字符,因此它不会与模式匹配,因此替换不会替换它.简单.


pax*_*blo 41

为了实用主义的利益,我倾向于将其作为一个三阶段过程:

:g/^    /s//XYZZYPARA/g
:g/ \+/s// /g
:g/^XYZZYPARA/s//    /g
Run Code Online (Sandbox Code Playgroud)

我不怀疑可能有更好的方法(可能使用宏或甚至纯正的正则表达方式)但我通常发现这在我匆忙时有效.当然,如果你有行开头XYZZYPARA,你可能想调整字符串:-)

这很好转:

    This is a new paragraph
spanning       two lines.
    And    so    is   this but on one line.
Run Code Online (Sandbox Code Playgroud)

成:

    This is a new paragraph
spanning two lines. 
    And so is this but on one line.
Run Code Online (Sandbox Code Playgroud)

旁白:如果你想知道为什么我用:g而不是:s,这只是习惯.:g可以做的一切都:s可以做得更多.它实际上是一种在选定行上执行任意命令的方法.执行命令恰好s在这种情况下,因此没有真正的区别,但是,如果你想成为vi超级用户,你应该:g在某个方面进行调查.

  • 是的,我的纯粹主义者/理想主义者很久以前开始退居二线.现在我只想完成工作,特别是如果备选方案是具有反向跟踪和前瞻功能的600字符正则表达式,当我必须在三个月内回来调试它时,我将无法理解:-) (2认同)

DrA*_*rAl 7

有很多很好的答案在这里(尤其是亚里士多德的:\zs\ze是非常值得学习).为了完整起见,您还可以使用负面的后置断言来做到这一点:

:%s/\(^ *\)\@<! \{2,}/ /g
Run Code Online (Sandbox Code Playgroud)

这表示"找到2个或更多的空格(' \{2,}'),前面没有'行的开头后跟零个或多个空格'".如果您希望减少反斜杠的数量,也可以这样做:

:%s/\v(^ *)@<! {2,}/ /g
Run Code Online (Sandbox Code Playgroud)

但它只能省你两个字!你也可以使用' +'替代的' {2,}',如果你不介意它做的冗余变化的负载(即改变为一个空格一个空格).

您也可以使用负面后卫来检查单个非空格字符:

:%s/\S\@<!\s\+/ /g
Run Code Online (Sandbox Code Playgroud)

这与(亚里士多德的一个略微修改版本的处理空格和制表符相同,以节省一点点打字)非常相似:

:%s/\S\zs \+/ /g
Run Code Online (Sandbox Code Playgroud)

看到:

:help \zs
:help \ze
:help \@<!
:help zero-width
:help \v
Run Code Online (Sandbox Code Playgroud)

和(全部阅读!):

:help pattern.txt
Run Code Online (Sandbox Code Playgroud)