【问题标题】:How to make perl regexes matches ASCII and Unicode如何使 perl 正则表达式匹配 ASCII 和 Unicode
【发布时间】:2016-04-12 12:38:52
【问题描述】:

我有一个程序来解析 Windows 打印机驱动程序的 inf 文件。

只要文件是 ASCII 格式,系统就可以正常工作。

因此,例如,正则表达式 m/^\[([^\]\]*)$/ 可以很好地匹配节标题。

对于 Unicode 行,该行匹配m/^\0\[([^\]\0\]*)$/,当然不是第一个。因此,文件未正确解析。

如何让 perl 正则表达式忽略 \0 字符?

【问题讨论】:

  • Config::Simple 应该能够读取 INF 文件。它们遵循 INI 文件的语法。但我不确定它是否能正确读取看起来像 cmets 的东西。我会尽量避免这个问题。

标签: regex perl unicode


【解决方案1】:

1) 确保您拥有 Perl 5.14 或更新版本。

2) 阅读perlre 联机帮助页,尤其是标题为“字符集修饰符”的部分

3) 根据最适合您需要的行为,在您的正则表达式中使用 /a、/u、/l 或 /d 标志。

【讨论】:

  • 问题是他的文本是使用UTF-16le编码的。这无济于事。
【解决方案2】:

您不能只是“忽略”空字符。这样数据中的任何非 ASCII 字符都不会被正确解释

听起来您正在尝试解析 UTF-16BE 编码的数据而不对其进行解码。使用核心 Encode 模块将其解码为 Perl 内部表示,像这样

use strict;
use warnings 'all';
use feature 'say';

use Encode;

my $bytes = "\0[\0x\0x\0x\0]";

my $string = decode('UTF-16BE', $bytes, Encode::FB_CROAK);

say $string;

输出

[xxx]

如果我对编码有误,请显示您输入字符串的转储,使用

use Data::Dumper;
$Data::Dumper::Useqq = 1;
$Data::Dumper::Terse = 1;

print Dumper $bytes;

【讨论】:

    【解决方案3】:

    始终解码您的输入并编码您的输出。具体来说,改变

    open(my $fh, '<', $qfn)
    

    open(my $fh, '<:encoding(UTF-16le)', $qfn)
    

    这会将文本从字节解码为代码点,让您的匹配工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-09-22
      • 1970-01-01
      • 1970-01-01
      • 2010-09-09
      • 1970-01-01
      • 2011-08-04
      • 1970-01-01
      相关资源
      最近更新 更多