【问题标题】:regular epxressions that matches the longest repeating sequence匹配最长重复序列的正则表达式
【发布时间】:2012-02-28 23:06:48
【问题描述】:

我想匹配至少重复一次的最长序列

拥有:

T_send_ack-new_amend_pending-cancel-replace_replaced_cancel_pending-cancel-replace_replaced

结果应该是:pending-cancel-replace_replaced

【问题讨论】:

  • REGEX 有语言约定吗?
  • 是的,有。这对于 POSIX 正则表达式是不可能的,您需要特定于引擎的功能,例如 PCRE 中的反向引用。

标签: regex text full-text-search


【解决方案1】:

试试这个

(.+)(?=.*\1)

here on Regexr

这将匹配具有至少一个字符的任何字符序列,该字符稍后会在字符串中重复。

您需要存储您的匹配项,然后再决定哪个匹配项最长。

此解决方案需要您的正则表达式支持反向引用和前瞻。

它将匹配具有至少一个字符.+ 的任何字符序列,并将其存储在组 1 中,因为它周围有括号。下一步是正向前瞻(?=.*\1),如果捕获的序列再次出现在字符串中的稍后位置,则为真。

【讨论】:

  • 这将匹配第一个重复的字符(即_),而不是最长的序列。
  • @M42 查看 Regexr 链接,它将匹配稍后重复的任何字符序列(意味着至少一个字符),你是对的,第一个匹配是“_”。
  • 好的,如果你添加global标志,它将匹配所有序列。
  • @M42 OP 没有提到他的语言,因此没有全局标志,因为那是 Perl,但是 +1 为您提供完整的解决方案。
  • 最快的回复获得被接受的投票。感谢您提供所有其他答案。
【解决方案2】:

使用 Perl 你可以做到:

s='T_send_ack-new_amend_pending-cancel-replace_replaced_cancel_pending-cancel-replace_replaced'
echo $s | perl -pe 's/([^\s]+)(?=.*?\1)/\1\n/g'

这给出了:

T_
send_
ac
k-
n
e
w_
a
mend
_pending-cancel-replace_replaced
_
cancel
_
p
e
n
d
in
g-
c
a
nce
l
-replace
_re
placed

然后您需要以任何语言或脚本对其进行后期处理以获得最长的文本。

一个可能的重复字符串的后处理可以使用 awk:

echo $s | perl -pe 's/([^\s]+)(?=.*?\1)/\1\n/g' | awk '{ if (length($0) > max) {max = length($0); maxline = $0} } END { print maxline }'

哪些打印:

_pending-cancel-replace_replaced

PS:注意这里最长的字符串是_pending-cancel-replace_replaced

【讨论】:

    【解决方案3】:

    我不得不承认,这个让我思考。很明显,使用正则表达式解决这个问题绝对需要积极的前瞻。无论如何,这是它在 Java 中的工作方式:

    public static String biggestOccurance(String input){
        Pattern p = Pattern.compile("(.+)(?=.*\\1)");
        Matcher m = p.matcher(input);
    
        String longestOccurence = "";
        while(m.find()){
            if(longestOccurence.length() < m.group(1).length()) longestOccurence = m.group(1);
        }
        return longestOccurence;
    }
    

    让我陷入困境的是

    \\1

    我知道你可以用

    引用 Java 中的反向引用

    $1

    但如果将 $1 替换为 \\1 它将不起作用。

    将不得不深入研究。

    干杯,尤金。

    【讨论】:

      【解决方案4】:

      这是一个完成这项工作的 perl 脚本:

      #!/usr/bin/perl 
      use strict;
      use warnings;
      use 5.010;
      
      my $s = q/T_send_ack-new_amend_pending-cancel-replace_replaced_cancel_pending-cancel-replace_replaced/;
      my $max = 0;
      my $seq = '';
      while($s =~ /(.+)(?=.*\1)/g) {
          if(length$1 > $max) {
              $max = length $1;
              $seq = $1;
          }
      }
      say "longuest sequence : $seq, length = $max"
      

      输出:

      longuest sequence : _pending-cancel-replace_replaced, length = 32
      

      【讨论】:

        猜你喜欢
        • 2013-12-30
        • 2012-03-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-03-24
        • 1970-01-01
        • 1970-01-01
        • 2018-10-22
        相关资源
        最近更新 更多