【问题标题】:Finding palindrome using regex使用正则表达式查找回文
【发布时间】:2014-04-16 11:02:14
【问题描述】:

这个问题试图理解以下答案之一:How to check that a string is a palindrome using regular expressions?

Markus Jarderot给出的答案是:

/^((.)(?1)\2|.?)$/

有人可以解释一下,这里到底发生了什么....我需要在Perl 中做类似的事情,但无法理解这个解决方案!!!

PS:我在 perl 方面不是很好,所以请放轻松......还有“如果你想严格的话,这不能被视为正则表达式” - 我读了这一行,所以 i我知道这不是严格的正则表达式

【问题讨论】:

  • Re“我需要在perl中做类似的事情”,即Perl。
  • Perl 正则表达式语法在perlre 中描述。
  • 查看 Perl 递归正则表达式的解释:rexegg.com/regex-recursion.html
  • 仅供参考,您不必使用正则表达式来检查字符串是否为回文。简单的案例是一个可以很容易调味的单衬:sub is_palindromic { $_[0] eq reverse $_[0] }
  • @NoobEditor,这不是对拼写的评论。我的意思是发布的代码是 Perl 代码,所以对 Perl 代码的请求是……奇数。 (perl 可执行文件或 Perl 语言都有意义。)

标签: regex perl palindrome


【解决方案1】:
  • ^ - 匹配字符串的开头
  • ( - 开始捕获组 #1
  • (.) - 匹配除换行符以外的任何单个字符,将其保存在捕获组 #2 中
  • (?1) - recurse = 将此组替换为整个正则表达式捕获组 #1
  • \2 - 与捕获组 #2 匹配相同的内容。这要求字符串的第一个和最后一个字符相互匹配
  • | - 创建一个替代方案
  • .? - 可选地匹配任何一个不是换行符的字符 - 这通过匹配空字符串(当整个字符串为偶数长度时)或单个字符(当它是奇数长度时)来处理递归的结束
  • ) - 结束捕获组 #1
  • $ - 匹配字符串结尾或字符串结尾的换行符之前。

递归(?1) 是关键。回文是一个空字符串、一个 1 字符的字符串或首尾字符相同且它们之间的子字符串也是回文的字符串。

【讨论】:

  • 1 个字符的字符串的第一个和最后一个字符相同。
  • 递归 (?1) 让我难过!! :\
  • @NoobEditor,它记录在标题“(?PARNO) (?-PARNO) (?+PARNO) (?R) (?0)”下
  • 偶数长度的回文呢?
  • @Atav32 阅读第 7 个项目符号。它解释了偶数和奇数情况。
【解决方案2】:

使用这个类似的函数可能更容易理解,它对数组做同样的事情:

sub palindrome {
  if (scalar(@_) >= 2) {
    my $first_dot = shift;
    my $slash_two = pop;
    return $first_dot eq $slash_two && palindrome(@_);
  } else {
    # zero or one items
    return 1;
  }
}

print "yes!\n" if palindrome(qw(one two three two one));
print "really?\n" if palindrome(qw(one two three two two one));

(?1) 表示法是对正则表达式中第一个括号开头的递归引用,\2 是在当前递归中对(.) 的反向引用。这两个锚定在“在当前递归深度匹配的内容”的开头和结尾处,因此其他所有内容都在下一个深度匹配。


ikegami 怀疑这更快:

sub palindrome {
   my $next = 0;
   my %symbols;
   my $s = join '', map chr( $symbols{$_} ||= $next++ ), @_;
   return $s =~ /^((.)(?1)\2|.?)\z/s;
}

【讨论】:

  • @ikegami,对于不理解最后一行的人来说,这个答案的重点不是速度,而是清晰度。
【解决方案3】:

我几天前制作了这个正则表达式。 如果您像这样使用它,它将为您提供特定文本中所有回文的数组。 该示例适用于#JavaScript,但您可以使用任何语言的 regEx 本身来完成这项工作。 非常适合 21 个字符或 21 位数字的单词。如果需要,您可以使其更准确。


const palindromeFinder = /\b(\w?)(\w?)(\w?)(\w?)(\w?)(\w?)(\w?)(\w?)(\w?)(\w)\S?\10\9\8\7\6\5\4\3\2\1\b/g;

console.log(inputString.match(palindromeFinder));

【讨论】:

  • 匹配任何不是回文的东西确实效率低下,因为正则表达式引擎将为每个\w?尝试匹配/不匹配字符的所有组合。这是由于其 21 个字符的限制,其用途有限。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多