Perl的正则表达式窒息的字符集的多个实例
题
我开始了在PHP中使用的preg_replace一些疯狂的失败和煮沸下来的问题的情况下使用土耳其虚线“i”和undotted“I”一起具有多于一个字符类的。下面是一个简单的测试案例在PHP:
<?php
echo 'match single normal i: ';
$str = 'mi';
echo (preg_match('!m[ıi]!', $str)) ? "ok\n" : "fail\n";
echo 'match single undotted ı: ';
$str = 'mı';
echo (preg_match('!m[ıi]!', $str)) ? "ok\n" : "fail\n";
echo 'match double normal i: ';
$str = 'misir';
echo (preg_match('!m[ıi]s[ıi]r!', $str)) ? "ok\n" : "fail\n";
echo 'match double undotted ı: ';
$str = 'mısır';
echo (preg_match('!m[ıi]s[ıi]r!', $str)) ? "ok\n" : "fail\n";
?>
在Perl 和相同的测试案例再次:
#!/usr/bin/perl
$str = 'mi';
$str =~ m/m[ıi]/ && print "match single normal i\n";
$str = 'mı';
$str =~ m/m[ıi]/ && print "match single undotted ı\n";
$str = 'misir';
$str =~ m/m[ıi]s[ıi]r/ && print "match double normal i\n";
$str = 'mısır';
$str =~ m/m[ıi]s[ıi]r/ && print "match double undotted ı\n";
在第一三个测试工作正常。最后一个不匹配。
为什么这工作精细的字符类一次,但不是在同一表达在第二时间?我怎样写一个表达式匹配的词像这样的需求,无论什么组合的字母它与写相匹配?
修改2:强>添加use utf8;
指令确实固定perl的版本。由于我原来的问题是用PHP程序,我只切换到Perl来看看它是否是在PHP中的错误,不帮我一大堆。的没有任何人知道的指示,使PHP在此不呛?的
解决方案
多字节序列不会做你在括号字符类想要什么,如果UTF-8被误解释为8位字节序列。想想吧。如果[nñm]
没有作为三个逻辑字符,但作为四个物理字节misconstructed,你只匹配其代码点是6E或C3或B1或6D的字符。
出于某些目的,你也许可以侥幸逃脱重写[nñm]
为(?:n|ñ|m)
。这只是取决于你在做什么。套管东西,将无法正常工作。
此外,Unicode有用于土耳其无点我特殊壳体的规则。
像PHP声音只是没有足够的现代化。叹息。
其他提示
您可能需要告诉Perl源文件包含UTF8字符。尝试:
#!/usr/bin/perl
use utf8; # **** Add this line
$str = 'mısır';
$str =~ m/m[ıi]s[ıi]r/ && print "match double undotted ı\n";
这不利于你用PHP,但有可能在PHP中的类似指令。否则,请尝试使用某种形式的转义序列,以避免把文字字符在你的源代码。我什么都不知道关于PHP,所以我不能与帮助。
<强> 修改 强>结果 我读的是PHP没有Unicode支持。因此,传递给它的输入的unicode很可能视为字节,该unicode被编码为字符串。
如果你可以放心,您的输入在为UTF-8,然后可以匹配针对ı
的UTF-8序列来这是\xc4 \xb1
如:
$str = 'mısır'; # Make sure this source-file is encoded as utf-8 or this match will fail
echo (preg_match('!m(i|\xc4\xb1)s(i|\xc4\xb1)r!', $str)) ? "ok\n" : "fail\n";
运作的?
修改再次:强>结果
我可以解释为什么你的前三个测试通过。让我们假设你的编码,ı
被编码为ABCDE
。然后PHP看到以下情况:
echo 'match single normal i: ';
$str = 'mi';
echo (preg_match('!m[ABCDEi]!', $str)) ? "ok\n" : "fail\n";
echo 'match single undotted ABCDE: ';
$str = 'mABCDE';
echo (preg_match('!m[ABCDEi]!', $str)) ? "ok\n" : "fail\n";
echo 'match double normal i: ';
$str = 'misir';
echo (preg_match('!m[ABCDEi]s[ABCDEi]r!', $str)) ? "ok\n" : "fail\n";
echo 'match double undotted ABCDE: ';
$str = 'mABCDEsABCDEr';
echo (preg_match('!m[ABCDEi]s[ABCDEi]r!', $str)) ? "ok\n" : "fail\n";
这使得它明显为什么前三个测试通过,最后一个失败。如果您使用的开始/结束锚^...$
我想你会发现只有第一个测试通过。