Vim :s 替换一行中出现的特定 N < g 次
Vim :s replace specific N < g occurrences on a line
我正在尝试使用逗号 (,) 来分隔前两个数字字段中的千位 vim command
%s/\([0-9]\)\([0-9]\)\([0-9]\)\([0-9]\);/,;/g
但在这种情况下,它还会在第二行的 9,995 中添加逗号,我可以用什么来替换特定的 N < g 出现。
输入
BitstreamCyberCJK;Freeware;30275;28686;v2.0 ;beta (1998-03-17)
Y.OzFontN;Freeware;21957;7621;v13.00 sfnt rev 9995; Pen-Ji (2010-08-24)
预期输出
BitstreamCyberCJK;Freeware;30,275;28,686;v2.0 ;beta (1998-03-17)
Y.OzFontN;Freeware;21,957;7,621;v13.00 sfnt rev 9995; Pen-Ji (2010-08-24)
有一种方法可以重复最后一个命令:@:
另外,您可以指定重复次数,例如:10@:
.
因此,从仅替换第一个匹配项开始:%s/\([0-9]\)\([0-9]\)\([0-9]\)\([0-9]\);/,;/
然后,因为我们已经完成了N个替换之一,所以重复N-1次。
例如,要替换前 10 个数字,请使用:
%s/\([0-9]\)\([0-9]\)\([0-9]\)\([0-9]\);/,;/
9@:
我会使用更短且更易于管理的搜索模式:
:%s/\(\d\)\(\d\{3}\);/,;/g
然后,我将删除 /g
标志以仅替换每行中的第一个匹配项,因为目标具体是 而不是 替换所有行中的所有匹配项:
:%s/\(\d\)\(\d\{3}\);/,;
然后,我会在每一行重复最后一个替换:
g&
参见 :help \d
、:help \{
、:help :s_flags
和 :help g&
。
首先,我建议您清理正则表达式:
:%s/\([0-9]\)\([0-9]\{3}\);/,;/g
其次,最后的 g
标志使 vim 替换所有出现的地方。没有标志,它只会替换第一个。由于 %
运行 是每行的替换,%s//g
将替换每行中的第一个匹配项。
由于您想要替换前两次出现的位置,您只需 运行 替换两次即可。然而,我们想要在这里优雅一点。有 :&
命令重复最后一次替换。我们甚至可以将它们链接在一起:
:%s/\([0-9]\)\([0-9]\{3}\);/,;/ | norm %&
更新:
其他解决方案也可以这样使用:
:%s/\([0-9]\)\([0-9]\{3}\);/,;/ | norm g&
或
:%s/\([0-9]\)\([0-9]\{3}\);/,;/ | norm :@
上面已经有很好的答案,但我将分享我将如何处理它。 (因为我不想数“N”有多少,我不想重复替换却发现我做了太多,等等)
我会使用上面列出的替换项之一,例如 :%s/\(\d\)\(\d\{3}\);/,;/g
。然后我 运行 进行第二次替换,搜索“rev”并删除逗号(如果存在):
%s/\(rev \d\),\(\d\{3\};\)//g
% g all lines, and all occurences on a line
s/ / / substitute
\( \) \( \) backref capture groups
rev \d text "rev " and a digit (backref 1)
, comma
\d\{3\}; three digits and a semicolon (backref 2)
backrefs 1 and 2
一些注意事项--
- 如果您知道“rev”在一行中只出现一次,那么您可以省略替换末尾的
g
。
- 如果“rev”以某种方式出现在其他
文件中的上下文——可能是像“Foo bar abbrev 4,321”这样的文本——
那么你要考虑到这一点。
- 如果没有“rev”后跟数字和逗号的匹配项,则 Vim 将给出“未找到模式”消息。
此外,这将搜索带逗号的四位数。如果你想删除逗号的五位或六位数字的机会,那么你会使用这个,这几乎是一样的:
%s/\(rev \d\{1,3\}\),\(\d\{3\}\);//g
\d\{1,3\} , 1 to 3 digits followed by a comma
我正在尝试使用逗号 (,) 来分隔前两个数字字段中的千位 vim command
%s/\([0-9]\)\([0-9]\)\([0-9]\)\([0-9]\);/,;/g
但在这种情况下,它还会在第二行的 9,995 中添加逗号,我可以用什么来替换特定的 N < g 出现。
输入
BitstreamCyberCJK;Freeware;30275;28686;v2.0 ;beta (1998-03-17)
Y.OzFontN;Freeware;21957;7621;v13.00 sfnt rev 9995; Pen-Ji (2010-08-24)
预期输出
BitstreamCyberCJK;Freeware;30,275;28,686;v2.0 ;beta (1998-03-17)
Y.OzFontN;Freeware;21,957;7,621;v13.00 sfnt rev 9995; Pen-Ji (2010-08-24)
有一种方法可以重复最后一个命令:@:
另外,您可以指定重复次数,例如:10@:
.
因此,从仅替换第一个匹配项开始:%s/\([0-9]\)\([0-9]\)\([0-9]\)\([0-9]\);/,;/
然后,因为我们已经完成了N个替换之一,所以重复N-1次。
例如,要替换前 10 个数字,请使用:
%s/\([0-9]\)\([0-9]\)\([0-9]\)\([0-9]\);/,;/
9@:
我会使用更短且更易于管理的搜索模式:
:%s/\(\d\)\(\d\{3}\);/,;/g
然后,我将删除 /g
标志以仅替换每行中的第一个匹配项,因为目标具体是 而不是 替换所有行中的所有匹配项:
:%s/\(\d\)\(\d\{3}\);/,;
然后,我会在每一行重复最后一个替换:
g&
参见 :help \d
、:help \{
、:help :s_flags
和 :help g&
。
首先,我建议您清理正则表达式:
:%s/\([0-9]\)\([0-9]\{3}\);/,;/g
其次,最后的 g
标志使 vim 替换所有出现的地方。没有标志,它只会替换第一个。由于 %
运行 是每行的替换,%s//g
将替换每行中的第一个匹配项。
由于您想要替换前两次出现的位置,您只需 运行 替换两次即可。然而,我们想要在这里优雅一点。有 :&
命令重复最后一次替换。我们甚至可以将它们链接在一起:
:%s/\([0-9]\)\([0-9]\{3}\);/,;/ | norm %&
更新: 其他解决方案也可以这样使用:
:%s/\([0-9]\)\([0-9]\{3}\);/,;/ | norm g&
或
:%s/\([0-9]\)\([0-9]\{3}\);/,;/ | norm :@
上面已经有很好的答案,但我将分享我将如何处理它。 (因为我不想数“N”有多少,我不想重复替换却发现我做了太多,等等)
我会使用上面列出的替换项之一,例如 :%s/\(\d\)\(\d\{3}\);/,;/g
。然后我 运行 进行第二次替换,搜索“rev”并删除逗号(如果存在):
%s/\(rev \d\),\(\d\{3\};\)//g
% g all lines, and all occurences on a line
s/ / / substitute
\( \) \( \) backref capture groups
rev \d text "rev " and a digit (backref 1)
, comma
\d\{3\}; three digits and a semicolon (backref 2)
backrefs 1 and 2
一些注意事项--
- 如果您知道“rev”在一行中只出现一次,那么您可以省略替换末尾的
g
。 - 如果“rev”以某种方式出现在其他 文件中的上下文——可能是像“Foo bar abbrev 4,321”这样的文本—— 那么你要考虑到这一点。
- 如果没有“rev”后跟数字和逗号的匹配项,则 Vim 将给出“未找到模式”消息。
此外,这将搜索带逗号的四位数。如果你想删除逗号的五位或六位数字的机会,那么你会使用这个,这几乎是一样的:
%s/\(rev \d\{1,3\}\),\(\d\{3\}\);//g
\d\{1,3\} , 1 to 3 digits followed by a comma