regex - Linux 或 Vim : How to find and replace matched string, 除了最后一个字符?

标签 regex vim regex-lookarounds

场景

假设我有一些文本文件:

savingstable
savings_proc.table

我想把它改成:

savings.table
savings_proc.table

我的解决方案

我把它分成两个命令:
%s/savings/savings\./g
在此之后,文件显示为:

savings.table
savings._proc.table

所以我按照命令执行:
%s/savings\._/savings_/g

问题

将问题分成两个编辑并不总是有效。有没有办法一步完成所有这些?

一步解决方案是匹配所有 savings[A-Za-z] 的情况,并将除最后一个字符以外的所有字符替换为 savings\.

一般来说,有没有一种方法可以替换自己匹配的字符串,排除匹配字符串中的某些字符?在这种情况下,我们希望排除最后一个字符。

最佳答案

在此特定场景中,%s/savings\zs\ze[^_]/./会工作,它也让你有机会做 :h \zs学习新东西,但如果您不解释更一般的用例,那么我们将无能为力。

A one step solution would be to match all cases of savings[A-Za-z] and replace everything but the last character with savings\. (Actually this would be savings., as you don't need to escape the . in the replacement string.)

好吧,您可以使用命令 %s/savings\([A-Za-z]\)/savings.\1/ 捕获最后一个字符并将其放回替换中.但是为什么不也捕获 savings部分,如 %s/\(savings\)\([A-Za-z]\)/\1.\2/ ?但在这一点上,我会回去智能地使用 \zs\ze .

Generally, is there a way to replace one's matched strings excluding certain characters in the matched string? In this case we would want to exclude the last character.

“排除某些字符”通常是不可能的,原因很明显:你有一个字符串(它可以有文字部分,例如 bla ,对捕获组的引用,例如 \1\2 , n...,和其他东西;但它们仍然加起来是一个字符串)来替换东西。而且这些东西不可能也不是字符串。换句话说,如果替换命令以 s/ABC/replacement/ 开头,没有办法“装饰” ABC或写 replacement这样 AC被替换但是B保持不变;如果你想保留 B ,您必须手动或通过反向引用将其放回原处,例如s/A\(B\)C/x\1y/ .

另一方面,您可以完全通过 \zs 排除搜索字符串的前导和尾随部分。和 \ze我从一开始就提到过。这两个分别是positive lookbehind和positive lookahead的特例,Vim通过\@<=实现。和 \@= .例如,%s/savings\zs\ze[^_]/./相当于可读性较差的 %s/\%(savings\)\@<=[^_]\@=/./ , 其中[^_]\@=正在匹配非 _无需“消耗”它们,就像 \ze[^_]在非 _ 之前结束比赛;同样\%(savings\)\@<=savings 之后匹配(必须分组,但没有必要记住它,所以我使用了 \%(\) 而不是 \(\))。

请注意,还有负面回顾 \@<!和负面前瞻\@! .它们中的所有 4 个统称为环视,并允许在正则表达式中放置一些非常复杂的逻辑。

关于regex - Linux 或 Vim : How to find and replace matched string, 除了最后一个字符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68833928/

相关文章:

javascript - 使用正则表达式模拟通配符(glob)

vim - vim sp 和 vsp 的合并历史记录?

regex - 匹配注释行的注释

regex - 可以分割具有相同嵌套括号的字符串的正则表达式

php - MySQL 中的正则表达式错误(相同的正则表达式在 PHP 中也有效)

python - 正则表达式删除连字符和空格

session - 如何在 Vim 的状态行中添加当前 session 文件名?

vim - 如何*直接*增加光标下的数字?

regex - 改进正则表达式以匹配包含至少有 N 个字母的字母数字单词的 url

java - 使用正则表达式替换不在括号中的逗号