php - Perl 正则表达式在字符集的多个实例上阻塞

标签 php regex perl unicode turkish

我一开始在 php 中使用 preg_replace 遇到了一些疯狂的失败,并将其归结为具有多个字符类同时使用土耳其语点缀“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";

前三个测试工作正常。最后一个不匹配。

为什么这一次作为字符类工作正常,但在同一表达式中第二次就不行了?我该如何编写一个表达式来匹配这样一个无论用什么字母组合都需要匹配的单词?

编辑:背景 the language problem我正在尝试编程。

编辑 2: 添加 use utf8; 指令确实修复了 perl 版本。由于我最初的问题是 php 程序,我只是切换到 perl 以查看它是否是 php 中的错误,所以这对我没有太大帮助。 有人知道使 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";

这很明显为什么前三个测试通过而最后一个测试失败。如果您使用开始/结束 anchor ^...$ 我想您会发现只有第一个测试通过。

关于php - Perl 正则表达式在字符集的多个实例上阻塞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4250120/

相关文章:

php - Money_format,移动 'currency name'

php - PHP PDO如何在注册时对密码进行哈希处理,然后在登录时“取消哈希处理”

c# - 正则表达式 - 用于从字符串中提取数据的各种正则表达式

javascript - 可以匹配空字符串的正则表达式正在破坏 javascript 正则表达式引擎

algorithm - sed优化(基于较小数据集的大文件修改)

mysql - 500 内部服务器错误 perl/数据库

php - 选择更好的选项 1) 使用文件或 2) 数据直接存入数据库

php - 有没有办法阻止访客查看该帖子?

regex - html 5 模式接受空格

perl - 我如何使用 Catalyst 的 auto 并开始?