Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex 正则表达式和索引don';不匹配unicode字符_Regex_String_Perl_Character Encoding - Fatal编程技术网

Regex 正则表达式和索引don';不匹配unicode字符

Regex 正则表达式和索引don';不匹配unicode字符,regex,string,perl,character-encoding,Regex,String,Perl,Character Encoding,我正在编写的库中的一个函数返回一个字符串,当试图通过正则表达式或index函数查找unicode字符时,该字符串会出现问题。字符串正常打印(使用Sublime text的控制台进行unicode打印),如下所示: <xml>V日한ế</xml> 它正在打印字符“日" 在正则表达式中为%x{65e5},问题字符串中的字符为%x{e6}%x{97}。其他unicode字符的打印方式也类似 有调试字符串和编码经验的人能告诉我为什么regex和index找不到我知道存在于字符串

我正在编写的库中的一个函数返回一个字符串,当试图通过正则表达式或
index
函数查找unicode字符时,该字符串会出现问题。字符串正常打印(使用Sublime text的控制台进行unicode打印),如下所示:

<xml>V日한ế</xml>
它正在打印字符“日" 在正则表达式中为
%x{65e5}
,问题字符串中的字符为
%x{e6}%x{97}
。其他unicode字符的打印方式也类似


有调试字符串和编码经验的人能告诉我为什么regex和
index
找不到我知道存在于字符串中的unicode字符,以及我如何让这些函数找到它们吗?

让我们制作一个可复制的测试用例:

  • 生成输入文件:

    $ perl -E'say "<xml>V\xe6\x97\xa5\xed\x95\x9c\xe1\xba\xbf</xml>"' >test.xml
    $ cat test.xml
    <xml>V日한ế</xml>
    
    现在它匹配了,因为我们已经从文件中读取了正确解码的代码点

  • 你得到了相同的输出吗?如果你没有得到类似的输出,你使用的是什么perl/OS组合(这是Ubuntu GNU/Linux上的perl 5.18.1)

    这段代码还有一些遗留问题:有多种方式来表示
    ế。因此,您应该规范化正则表达式中的字符串和输入:

    use Unicode::Normalize 'NFC';
    my $regex_body = NFC "V日한ế";
    my $s          = NFC scalar <$fh>;
    
    ... m/\Q$regex_body/ ...
    
    使用Unicode::规范化“NFC”;
    我的$regex_body=NFC“V日한ế";
    my$s=NFC标量;
    …m/\Q$regex\u body/。。。
    
    看起来像您在utf16中的输入,将其解码为perl内部格式Halleujah,它工作了!我使用编码模块将字符串解码为
    utf-8
    ,结果一切正常。字符串源于
    XML::LibXML::Document::toString
    $ cat test.pl
    use strict; use warnings; use utf8; use autodie; use feature 'say';
    open my $fh, "<", shift @ARGV;
    
    my $s = <$fh>;
    say "$s ", $s =~ m/V日한ế/ ? "matches" : "doesn't match";
    say "string = ", map { sprintf "\\x{%x}", ord } split //, $s;
    $ perl test.pl test.xml
    <xml>V日한ế</xml>
     doesn't match
    string = \x{3c}\x{78}\x{6d}\x{6c}\x{3e}\x{56}\x{e6}\x{97}\x{a5}\x{ed}\x{95}\x{9c}\x{e1}\x{ba}\x{bf}\x{3c}\x{2f}\x{78}\x{6d}\x{6c}\x{3e}\x{a}
    
    $ cat test-utf8.pl
    use strict; use warnings; use utf8; use autodie; use feature 'say';
    open my $fh, "<:utf8", shift @ARGV;
    
    my $s = <$fh>;
    say "$s ", $s =~ m/V日한ế/ ? "matches" : "doesn't match";
    say "string = ", map { sprintf "\\x{%x}", ord } split //, $s;
    $ perl test-utf8.pl test.xml
    Wide character in say at test-utf8.pl line 5, <$_[...]> line 1.
    <xml>V日한ế</xml>
     matches
    string = \x{3c}\x{78}\x{6d}\x{6c}\x{3e}\x{56}\x{65e5}\x{d55c}\x{1ebf}\x{3c}\x{2f}\x{78}\x{6d}\x{6c}\x{3e}\x{a}
    
    use Unicode::Normalize 'NFC';
    my $regex_body = NFC "V日한ế";
    my $s          = NFC scalar <$fh>;
    
    ... m/\Q$regex_body/ ...