这个问题是为了理解一个回答而提出的:如何使用正则表达式检查字符串是否为回文?
Markus Jarderot 给出的答案是:
/^((.)(?1)\2|.?)$/
有人能解释一下,这里到底发生了什么...我需要在Perl
中做类似的事情,但是无法理解这个解决方案!!!
附注:我不太擅长Perl,所以请轻一点...还有,“如果你想严格一点,这不能被认为是正则表达式”——我看到了这句话,所以我知道这不是严格的正则表达式
这个问题是为了理解一个回答而提出的:如何使用正则表达式检查字符串是否为回文?
Markus Jarderot 给出的答案是:
/^((.)(?1)\2|.?)$/
有人能解释一下,这里到底发生了什么...我需要在Perl
中做类似的事情,但是无法理解这个解决方案!!!
附注:我不太擅长Perl,所以请轻一点...还有,“如果你想严格一点,这不能被认为是正则表达式”——我看到了这句话,所以我知道这不是严格的正则表达式
^
- 匹配字符串的开头(
- 开始捕获组 #1(.)
- 匹配除换行符以外的任何单个字符,并将其保存在捕获组 #2 中(?1)
- 递归 = 将此组替换为整个正则表达式捕获组 #1\2
- 匹配与捕获组 #2 相同的内容。这要求字符串的第一个和最后一个字符相匹配。|
- 创建一个可选项.?
- 可选地匹配除换行符以外的任何一个字符 - 这用于处理递归的结尾,通过匹配空字符串(当整个字符串长度为偶数时)或单个字符(当它是奇数长度时)来结束递归。)
- 结束捕获组 #1$
- 匹配字符串的结尾或字符串末尾的换行符。关键在于递归部分(?1)
。回文是一个空字符串、一个单字符字符串或一个首尾字符相同并且它们之间的子字符串也是回文的字符串。
(?1)
是让我困惑的地方!!:\ - NoobEditor这个类比函数可能更容易理解,它用于处理数组的同样操作:
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;
}
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个字符限制而受到的有限用处。 - Abigail
perldoc perlretut
- 递归模式 - Zaidsub is_palindromic { $_[0] eq reverse $_[0] }
。 - Zaidperl
可执行文件或Perl语言都有意义。) - ikegami