Vim正则表达式:替换引号内的空格

8

我有以下格式的文本:

ERR_OUT_OF_MEM, "ERR OUT OF MEM"
ERR_SOMETHING_BAD, "ERR SOMETHING BAD"

我想用下划线替换文本中所有在引号内的空格:
 ERR_OUT_OF_MEM, "ERR_OUT_OF_MEM"
 ERR_SOMETHING_BAD, "ERR_SOMETHING_BAD"

The best regex I could come up with is:

\("\w\+\)\@<= 

但是这样只会找到每个引用字符串中的第一个空格,我需要重复多次才能达到预期效果。

有什么方法可以一次性完成吗?

谢谢!

4个回答

10

确实有一种在一次扫描中有效的零长度模式,但我从来没有太成功地使用过它们,所以我更喜欢这种方法:

:%s/\%("[^"]*"\)*\("[^"]*"\)/\=substitute(submatch(1), ' ', '_', 'g')/g
注意:双引号被分组为2个2个,以便不改变其格式。
foo bar "foo bar" "foo barr"

进入

foo bar "foo_bar"_"foo_barr"

编辑:正如rampion指出的那样,以下内容已经足够:

%s/"[^"]*"/\=substitute(submatch(0), ' ', '_', 'g')/g

1
为什么不直接使用/"[^"]*"/模式呢?我不明白跳过初始引号对(\%("[^"]*"\)*)对你有什么好处。 - rampion
好的观点。 我被说服认为搜索将在闭引号之后而非开引号之后重新开始。我更正了正则表达式。谢谢。 - Luc Hermitte

6

这不是一个通用解决方案,因为它将匹配出现在双引号后的任何位置的空格,但它应该适用于您指定的格式的字符串:

s/\v(\".*)@<= /_/g

我使用了\v(verymagic)标记,因为我认为它使正则表达式更易读,并且包括了整个替换命令,因为末尾的'g'很重要。

对于那些在家跟进的人,这个正则表达式首先使用\v设置了'verymagic'模式。然后定义了token (\".*),大致意思是“一个双引号和其他任何字符”,并使用前瞻断言@<=来表示“只匹配最后一个token之后的内容” - 换句话说,只匹配在双引号之后出现的内容。最后有一个空格,这是实际匹配的内容,替换项是下划线,这是我们想要替换的内容,g表示“替换所有匹配项”,因此我们不仅获取第一个匹配项。


这个可以运行,但它也会替换掉我在行末的空格。 - vicky.dev
啊。是的,如果你有尾随空格,你需要一个更复杂的方法。上面的Luc应该可以解决它。 - John Hyland

0

我的 PatternsOnText 插件 提供了一个 :SubstituteInSearch 命令。使用它,您可以先搜索引号字符串,然后只在匹配项中执行 :substitute

/".\{-}"
:SubstituteInSearch/_/ /g

0
我认为这个正则表达式可能会有用:
:%s/\(^.\{-}"\)\| /_\1/g | %s/^_//g
从:
ERR_OUT_OF_MEM, "ERR OUT OF MEM"
ERR_SOMETHING_BAD, "ERR SOMETHING BAD"
到:
ERR_OUT_OF_MEM, "ERR_OUT_OF_MEM"
ERR_SOMETHING_BAD, "ERR_SOMETHING_BAD"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接