vim regex只用一个空格replace多个连续的空格
我经常使用文本文件,这些文本文件有不同数量的空格作为单词分隔符(像Word这样的文本处理程序可以完成这项工作,因为某些字体的字母大小不同,所以可以分配相当大的空白量,即使在这种情况下,保存为纯文本)。
我想自动化replace具有单个空格的可变长度的这些空白序列的过程。 我怀疑一个正则expression式可以做到这一点,但也有段落开头(通常是其中四个,但不是总是)的空格,我想让这个空格不变,所以基本上我的正则expression式也不应该触及领先的空格,增加了复杂性。
我使用的是vim,所以如果这是可行的,那么vim正则expression式中的正则expression式对我来说是非常有用的。
我目前的进展如下所示:
:%s/ \+/ /g
但它不能正常工作。
我也正在考虑编写一个可以parsing文本行的vim脚本,通过char处理每一行字符,并在第一行之后跳过空格,但我有一种感觉,这将是矫枉过正的。
为了实用主义的利益,我倾向于把它作为一个三阶段的过程:
:g/^ /s//XYZZYPARA/g :g/ \+/s// /g :g/^XYZZYPARA/s// /g
我不怀疑可能有一个更好的方法(可能使用macros或者甚至是一个纯正则expression式的方式),但是当我匆忙的时候,我通常会发现这个方法是有效的。 当然,如果你有以XYZZYPARA
开头的XYZZYPARA
,你可能需要调整string:-)
这是很好的转向:
This is a new paragraph spanning two lines. And so is this but on one line.
成:
This is a new paragraph spanning two lines. And so is this but on one line.
旁白:如果你想知道为什么我使用
:g
而不是:s
,那只是习惯。:g
可以做所有事情:s
可以,还有更多。 这实际上是一种在选定行上执行任意命令的方法。 在这种情况下执行的命令恰好是s
,所以没有实际的区别,但是,如果你想成为一个vi
用户,你应该在某个时刻考虑:g
。
这将取代2个或更多的空间
s/ \{2,}/ /g
或者你可以在你的版本之前添加一个额外的空格
s/ \+/ /g
这将做的伎俩:
%s![^ ]\zs \+! !g
通过使用\zs
和\ze
元序列,Vim中的许多replace可以比其他正则expression式更容易完成。 他们所做的是从最终结果中排除部分匹配,或者序列之前的部分( \zs
,“s”代表“开始于此”)或者之后的部分( \ze
,“e”代表“结束于此” )。 在这种情况下,模式必须首先匹配一个非空格字符( [^ ]
),但是下面的\zs
表示最后的匹配结果(它将被replace) 在该字符之后开始。
由于没有办法在行前的空格前面有一个非空格字符,所以不会被模式匹配,所以replace不会替代它。 简单。
这里有很多很好的答案(特别是亚里士多德的: \zs
和\ze
很值得学习)。 只是为了完整性,你也可以用负面的后视断言来做到这一点:
:%s/\(^ *\)\@<! \{2,}/ /g
这就是说:“find两个或更多的空格( ' \{2,}'
),这些空格之前没有”行后跟零个或多个空格“。 如果你想减less反斜杠的数量,你也可以这样做:
:%s/\v(^ *)@<! {2,}/ /g
但它只能节省你两个字符! 如果您不介意执行冗余更改(即将单个空间更改为单个空间),也可以使用' +'
而不是' {2,}'
。
您也可以使用负面后视来检查单个非空格字符:
:%s/\S\@<!\s\+/ /g
这与(为了节省一些input而将亚里士多德的空间和标签作为相同处理的稍微修改过的版本)大致相同:
:%s/\S\zs \+/ /g
看到:
:help \zs :help \ze :help \@<! :help zero-width :help \v
和(阅读所有!):
:help pattern.txt
这是否工作?
%s/\([^ ]\) */\1 /g
我喜欢这个版本 – 它类似于亚里士多德Pagaltzis的前瞻版本,但我觉得更容易理解。 (可能只是我不熟悉\ zs)
s/\([^ ]\) \+/\1 /g
或所有空白
s/\(\S\)\s\+/\1 /g
我把它理解为“用一些东西和一个空格代替空间之外的所有事物”。
回答; 但尽pipe如此,我仍然抛弃了我的工作stream程。
%s/ / /g @:@:@:@:@:@:@:@:@:@:@:@:(repeat till clean)
快速和简单的记住。 上面有一个更优雅的解决scheme。 但只是我的.02。