如何对俄语字母进行不区分大小写的正则表达式匹配?

时间:2010-03-30 08:15:04

标签: regex perl internationalization locale

我有目录路径列表,需要过滤掉其中一些路径。我的匹配模式采用非Unicode编码。

我尝试了以下内容:

require 5.004;
use POSIX qw(locale_h);
my $old_locale = setlocale(LC_ALL);
setlocale(LC_ALL, "ru_RU.cp1251");

@{$data -> {doc_folder_rights}} = 
       grep {
              # catalog path pattern in $_REQUEST{q}
              $_->{doc_folder} =~/$_REQUEST{q}/i; 
            } 
            @{$data -> {doc_folder_rights}};

setlocale(LC_ALL, $old_locale);

当模式包含russsian字母时,我需要的是不区分大小写的regexp模式匹配。

1 个答案:

答案 0 :(得分:2)

您的代码存在多个(潜在)问题:

  1. 您的代码会过滤掉$_REQUEST{q}中的正则表达式匹配的所有doc_folders,但问题表明您想要反其道而行之。

  2. 您可能遇到编码问题。设置语言环境(使用setlocale)会改变perl对upper-&的处理。小写转换,但不会更改任何编码。您需要确保正确解释$_REQUEST{q}

  3. 为简单起见,您可以假设任何Perl-string在某些内部表示中包含您不需要详细了解的Unicode数据。只有当Perl执行I / O时,才会进行隐式或显式转换。从stdin,ARGV或环境读取时,Perl假定使用当前语言环境对字节进行编码并隐式转换。

    如果您遇到编码问题,可通过以下几种方法进行修复:

    1. 修复Perl运行的环境,以便从一开始就知道正确的语言环境。这将修复隐式转换。
    2. 在从文件句柄加载$_REQUEST的不太可能的情况下,您可以使用binmode($fh, ":encoding(cp1251)");明确告诉Perl进行转换。在阅读$_REQUEST
    3. 之前执行此操作
    4. $string = Encode::decode(Encoding, $octets)函数告诉Perl忘记它对$octets编码的假设,而是将$octets的内容视为需要转换为Unicode的字节流使用Encoding。在触摸$octets的内容之前,您需要这样做,否则可能会发生奇怪的事情。
    5. 由于$_REQUEST可能是由某些cgi-module加载的,并且可能在传输过程中进行了url编码,因此您可以告诉cgi-module如何正确地进行解码。