【问题标题】:Perl regular expression removing duplicate consecutive substrings in a stringPerl正则表达式删除字符串中重复的连续子字符串
【发布时间】:2011-07-29 15:25:13
【问题描述】:

我试图对这个特定问题进行搜索,但我得到的只是删除重复的行或删除由分隔符分隔的重复字符串。

我的问题略有不同。我有一个字符串,例如

    "comp name1 comp name2 comp name2 comp name3" 

我想删除重复的 comp name2 并只返回

    "comp name1 comp name2 comp name3" 

它们不是连续的重复词,而是连续的重复子串。有没有办法使用正则表达式来解决这个问题?

【问题讨论】:

  • 如果你有 ` "comp name1 comp name2 comp name2 comp name3 comp name4 comp name2" 怎么办?输出会是什么?
  • 嗨@kurumi,我只对连续重复感兴趣。因此,第二个(或输入中的第三个)comp name2 将保持不变。
  • 必须是正则表达式吗?恕我直言,字符串方法会更好。

标签: regex perl substring


【解决方案1】:
s/(.*)\1/$1/g

请注意,此正则表达式的运行时间是字符串长度的二次方。

【讨论】:

  • 我知道时间复杂度。在我的情况下,这些是相当短的字符串(最多约 100 个字符),不会花费那么长时间。
  • @btilly : 行而不是字符串同样的问题怎么样????..如果我有连续的重复行??
  • @unkaitha: perl -ne 'print unless $seen{$_}++' file.txt > no_dupe_lines.txt
【解决方案2】:

这对我有用(MacOS X 10.6.7,Perl 5.13.4):

use strict;
use warnings;

my $input = "comp name1 comp name2 comp name2 comp name3" ;
my $output = "comp name1 comp name2 comp name3" ;

my $result = $input;
$result =~ s/(.*)\1/$1/g;

print "In:   <<$input>>\n";
print "Want: <<$output>>\n";
print "Got:  <<$result>>\n";

关键点是匹配中的'\1'。

【讨论】:

  • @btilly 的解决方案略有不同。谢谢,但必须像以前那样和另一个人一起去。
【解决方案3】:

为了避免删除重复字符中的术语(例如comm1 -> com1)括号.*在正则表达式中使用\b。

s/(\b.*\b)\1/$1/g

【讨论】:

    【解决方案4】:

    我从不使用支持此功能的语言,但由于您使用的是 Perl ...

    去这里..和see this section....

    有用的例子:检查重复的单词

    编辑文本时,“the”之类的双字很容易进入。在文本编辑器中使用正则表达式 \b(\w+)\s+\1\b,您可以轻松找到它们。要删除第二个单词,只需输入 \1 作为替换文本,然后单击替换按钮。

    【讨论】:

    • 请,请,请。不要称语言为“珍珠”。它是“Perl”,可执行文件是“perl”。
    • @btilly:为他修复 - 我同意 100%。此外,问题不在于简单的“双重词”;它是关于“双重短语”,其中短语可能包含多个单词。您给出的答案可以扩展到所需的答案,但是...
    • 我在搜索中发现了这个,但它只适用于重复的单词而不是字符串。我的子字符串中有单词边界,所以这不起作用。
    • 是的,我应该使用“双短语”而不是子字符串。
    【解决方案5】:

    如果您需要在线性时间内运行的东西,您可以split 字符串并遍历列表:

    #!/usr/bin/perl                                                                                                                                                                                       
    
    use strict;
    use warnings;
    
    my $str = "comp name1 comp name2 comp name2 comp name3";
    my @elems = split("\\s", $str);
    my $prevComp;
    my $prevFlag = -1;
    foreach my $elemIdx (0..(scalar @elems - 1)) {
        if ($elemIdx % 2 == 1) {
            if (defined $prevComp) {
                if ($prevComp ne $elems[$elemIdx]) {
                    print " $elems[$elemIdx]";
                    $prevFlag = 0;
                }
                else {
                    $prevFlag = 1;
                }
            }
            else {
                print " $elems[$elemIdx]";
            }
            $prevComp = $elems[$elemIdx];
        }
        elsif ($prevFlag == -1) {
            print "$elems[$elemIdx]";
            $prevFlag = 0;
        }
        elsif ($prevFlag == 0) {
            print " $elems[$elemIdx]";
        }
    }
    print "\n";
    

    可能很脏,但应该运行得更快。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-11
      • 2021-03-03
      • 1970-01-01
      • 2019-05-12
      • 2018-01-26
      • 1970-01-01
      相关资源
      最近更新 更多