我有一个需要替换字符串中第n个子字符串的场景。s/sub-string/new-string/g;将替换所有的子字符串,但我需要在特定情况下这样做。请帮我一下。
s/sub-string/new-string/g;
dluptydi1#
要使用sed替换第n次出现的字符串,可以使用以下命令:
sed
sed 's/find_string/replace_string/n'
要替换子串,我们需要知道你想替换什么。给予个例子。
hm2xizp92#
这个问题可能很有趣:Perl regex replace count你可以这样做:
use strict; use warnings; my $count = 3; my $str = "blublublublublu"; $str =~ s/(lu)/--$count == 0 ? "LA":$1/ge; print $str;
dldeef673#
试试这个:
s/(sub-string{2,2})sub-string/$1new-string/
根据您的需要调整2(它是您的'n'-1)。注意在这些子字符串之间可能没有分隔符。例如' abcabcabc '可以使用但' abcdefabcabc '不能
imzjd6km4#
你也可以这样做
my $i=0; s/(old-string)/++$i%3 ? $1 : "new_string"/ge;
dw1jzc5e5#
我真的相信,除非真的有必要(或者除非你只是为了好玩),否则在正则表达式中构建额外的复杂性是没有意义的。在我实际计划使用的代码中,我会保持它的简单性,就像这样:
my $string = "one two three four five"; $string =~ m/\w+\s*/g for 1 .. 2; substr( $string,pos($string) ) =~ s/(\w+)/3/; print "$string\n";
在标量上下文中使用m//g会导致它在for循环的每次迭代中匹配一次。在每次迭代中,pos()都会跟踪$string上最近子匹配的结尾。一旦您完成了“n”次迭代(本例中为两个),您可以将pos()插入substr()。使用substr($string...作为左值。它将约束regexp匹配从您在第二个参数中指定的任何位置开始。我们将在此处插入pos,这约束它从上一个匹配停止的地方进行下一个匹配。此方法消除了显式计数器(尽管for循环本质上是相同的,只是没有指定计数器变量)。这种方法比s//condition ? result : result/eg方法伸缩性更好,因为它将在第三次匹配完成后停止,而不是继续尝试匹配,直到到达一个可能很大的字符串的末尾。换句话说,s///eg方法不约束匹配,它仅有条件地处理任意大量成功匹配的结果。在前一个关于同一主题的问题中,我曾经在s///运算符的左侧嵌入了一个计数器,虽然它在那个特定的情况下有效,这不是一个理想的解决方案,因为它很容易被回溯所抛弃。这是另一种情况,保持它的简单性本来是最好的方法。我在这里提到它,以便您可以避免尝试这种技巧的诱惑(除非你想从回溯中获得乐趣)。我在这里公布的方法,我相信是非常清楚的;你看着它就知道发生了什么匹配两次,跟踪上次匹配的位置,现在用替换匹配第三次。你可以有聪明,你可以有效率,你可以有清晰。但有时你不能三个都有。在这里你可以有效率和清晰。
m//g
for
pos()
$string
substr()
substr($string...
pos
s//condition ? result : result/eg
s///eg
tuwxkamq6#
s/((old-string).*?){2}\2/\1\1new-string/
nqwrtyyt7#
请参见@-和@+的perlvar。
@-
@+
my $str= "one two three four five"; if ( $str =~ /(?: (\w+) .*? ){3}/x ) { substr $str, $-[1], $+[1] - $-[1], "-c-e-n-s-o-r-e-d-"; } print $str, "\n";
正则表达式找到第3个示例,并在$1中捕获其起始字。
7条答案
按热度按时间dluptydi1#
要使用
sed
替换第n次出现的字符串,可以使用以下命令:要替换子串,我们需要知道你想替换什么。给予个例子。
hm2xizp92#
这个问题可能很有趣:Perl regex replace count
你可以这样做:
dldeef673#
试试这个:
根据您的需要调整2(它是您的'n'-1)。注意在这些子字符串之间可能没有分隔符。例如' abcabcabc '可以使用但' abcdefabcabc '不能
imzjd6km4#
你也可以这样做
dw1jzc5e5#
我真的相信,除非真的有必要(或者除非你只是为了好玩),否则在正则表达式中构建额外的复杂性是没有意义的。在我实际计划使用的代码中,我会保持它的简单性,就像这样:
在标量上下文中使用
m//g
会导致它在for
循环的每次迭代中匹配一次。在每次迭代中,pos()
都会跟踪$string
上最近子匹配的结尾。一旦您完成了“n”次迭代(本例中为两个),您可以将pos()
插入substr()
。使用substr($string...
作为左值。它将约束regexp匹配从您在第二个参数中指定的任何位置开始。我们将在此处插入pos
,这约束它从上一个匹配停止的地方进行下一个匹配。此方法消除了显式计数器(尽管for循环本质上是相同的,只是没有指定计数器变量)。这种方法比
s//condition ? result : result/eg
方法伸缩性更好,因为它将在第三次匹配完成后停止,而不是继续尝试匹配,直到到达一个可能很大的字符串的末尾。换句话说,s///eg
方法不约束匹配,它仅有条件地处理任意大量成功匹配的结果。在前一个关于同一主题的问题中,我曾经在s///运算符的左侧嵌入了一个计数器,虽然它在那个特定的情况下有效,这不是一个理想的解决方案,因为它很容易被回溯所抛弃。这是另一种情况,保持它的简单性本来是最好的方法。我在这里提到它,以便您可以避免尝试这种技巧的诱惑(除非你想从回溯中获得乐趣)。
我在这里公布的方法,我相信是非常清楚的;你看着它就知道发生了什么匹配两次,跟踪上次匹配的位置,现在用替换匹配第三次。你可以有聪明,你可以有效率,你可以有清晰。但有时你不能三个都有。在这里你可以有效率和清晰。
tuwxkamq6#
试试这个:
nqwrtyyt7#
请参见
@-
和@+
的perlvar。正则表达式找到第3个示例,并在$1中捕获其起始字。