【问题标题】:Substitute same number of repeated characters with others using Regex使用 Regex 将相同数量的重复字符替换为其他字符
【发布时间】:2014-02-18 17:27:50
【问题描述】:

我想用其他字符替换相同数量的重复字符,如果它在字符串的开头重复。最小重复次数应大于 2。

例如:$string = 'bbbbabcdeeeee' 这里的bbbb应该换成yyyy

但是如果 $string = 'bbcccccccddddddeeeffdfg' 不应该替换任何东西,因为第一个重复字符不超过两次

$string =~ s/^(b){3,}/y/ 将仅将超过 2 b 替换为仅 1 y

是否可以使用一行正则表达式进行替换? 注意:如果有人能用 Perl 或 Python 响应,那就太好了。

【问题讨论】:

  • 您希望使用哪种语言/工具?
  • 它的 Perl 编程语言。

标签: regex string perl


【解决方案1】:

你可以使用这样的代码:

$string='bbbbcccccccddddddeeeffdfg';
$string =~ s/^((\w)\2{2,})/'y' x length($1)/e;
print $string. "\n";

输出

yyyycccccccddddddeeeffdfg
  • /e -> 替换执行代码
  • 'y' x length($1) -> 重复字符 'y' 与匹配组 #1 的长度一样多

【讨论】:

  • 使其通用; $string =~ s/^((\w)\2{2,})/'y' x length($1)/e;
  • length($1) 将是总字符的长度,而不仅仅是单词的长度。即 bb.bb.bb.mgm s/^((bb\.){2,})/'y' x 长度($1)/e;会像这样替换 yyyyyyyyymgm 而不是 yyymgm
  • 它可以调整为点字符,但点也可以是第一个字符吗?另请注意,在这种情况下,它不会是纯粹的重复。
  • \2 是对匹配组#2 的反向引用,即\w 匹配的第一个字符。如果您只想匹配任何东西,那么$string =~ s/^((.)\2{2,})/'y' x length($1)/e; 将起作用。 {2,} 存在,因为已经进行了一场匹配,2 and more 需要进一步匹配。
  • 感谢错过了 prel 正则表达式手册中的那部分:perldoc.perl.org/perlre.html
【解决方案2】:

怎么样:

my $re = qr~^((.)\2{2,})~;
while(<DATA>) {
    chomp;
    s:$re:'y' x length($1):e;
    say;
}


__DATA__
bbbbabcdeeeeee
bbcccccccddddddeeeffdfg
xxxxxx

输出:

yyyyabcdeeeeee
bbcccccccddddddeeeffdfg
yyyyyy

【讨论】:

    【解决方案3】:

    我不知道您不希望使用哪种语言,但我会制作一个 php 脚本示例,您可以将其转换为您选择的语言:

    php > echo preg_replace('/([^b])b{3}([^b])/','$1yyy$2','aaabbbccc');
    aaayyyccc
    php > echo preg_replace('/([^b])b{3}([^b])/','$1yyy$2','aaaabbbbcccc');
    aaaabbbbcccc
    

    编辑

    如果您只想匹配开始字符,请使用刻度字符:

    php > echo preg_replace('/^b{3}([^b])/','yyy$2','aaaabbbbcccc');
    aaaabbbbcccc
    php > echo preg_replace('/^b{3}([^b])/','yyy$2','bbbbcccc');
    bbbbcccc
    php > echo preg_replace('/^b{3}([^b])/','yyy$2','bbbcccc');
    yyyccc
    php > echo preg_replace('/^b{3}([^b])/','yyy$2','bbcccc');
    bbcccc
    

    perl 版本:

    #/usr/bin/perl
    $string = 'bbbccc';
    $string =~ s/^b{3}([^b])/yyy$1/;
    print $string;
    $string = 'bbcc';
    $string =~ s/^b{3}([^b])/yyy$1/;
    print $string;
    $string = 'bbbbcccc';
    $string =~ s/^b{3}([^b])/yyy$1/;
    print $string;
    

    【讨论】:

    • 它应该只在字符串的开头检查重复字符,并且只有起始字符串会被替换。您的代码正在检查字符串的中间!
    • 再一次,我没有说只有 3 个,它可能是三个或更多:)
    【解决方案4】:

    如果您只想替换特定字符,那么在 bash(使用 sed)中,您可以使用以下内容:

    # echo aabcddd | sed '/\(a\)\{3,\}/{s/a/y/g}'
    aabcddd
    # echo aaabcddd | sed '/\(a\)\{3,\}/{s/a/y/g}'
    yyybcddd
    

    【讨论】:

    • 它会错误地将aaabcaaddd替换为yyybcyyddd
    猜你喜欢
    • 1970-01-01
    • 2015-08-30
    • 2011-11-19
    • 2016-01-29
    • 2021-11-02
    • 1970-01-01
    • 1970-01-01
    • 2015-04-18
    • 1970-01-01
    相关资源
    最近更新 更多