【问题标题】:Does Perl's /m regex modifier match differently on Windows?Perl 的 /m 正则表达式修饰符在 Windows 上的匹配是否不同?
【发布时间】:2010-09-17 21:20:45
【问题描述】:

以下 Perl 语句在 Unixish 机器上的行为相同。它们在 Windows 上的行为是否不同?如果是,是不是因为魔法\n?

  split m/\015\012/ms, $http_msg;
  split m/\015\012/s, $http_msg;

我在我的一个 CPAN 模块上从 Win32 烟雾测试仪获得了 failure。看起来这是一个 \r\n vs \n 问题。我最近所做的一项更改是将 //m 添加到我的正则表达式中。

【问题讨论】:

    标签: windows regex perl multiline


    【解决方案1】:

    对于这些正则表达式:

    m/\015\012/ms
    m/\015\012/s
    

    /m 和 /s 都没有意义。

    • /s:使. 也匹配\n。 您的正则表达式不包含 .
    • /m:使^ 和$ 匹配字符串中嵌入的\n 旁边。 您的正则表达式不包含 ^ 或 $ 或其同义词。

    如果您的输入句柄(套接字?)在文本模式下工作,确实有可能,\r (\015) 字符将在 Windows 上被删除。

    那么,该怎么办?我建议将 \015 字符设置为可选,并针对

    /\015?\012/
    

    不需要 /m、/s 甚至前导 m//。那些只是货物崇拜。

    【讨论】:

    • 啊!我认为您是对的,而我在使用正则表达式修饰符时走错了路。我正在使用 `` 从子进程获取输入,但从未想过要担心 binmode...
    【解决方案2】:

    没有魔法\n。 \n 和 \r 始终只表示一个字符,并且在所有基于 ASCII 的平台上分别为 \cJ 和 \cM。 (EBCDIC 平台(出于显而易见的原因)和 MacOS Classic(其中 \n 和 \r 均表示 \cM)是例外。)

    发生在 Windows 上的神奇之处在于,当通过标记为处于文本模式的文件句柄执行 I/O 时,\r\n 在读取时被转换为 \n,在写入时反之亦然。 (另外,\cZ 表示文件结束 - 令人惊讶!)这是在 C 运行时库层完成的。

    你需要binmode你的套接字来解决这个问题。

    您还应该从模式中删除 /s 和 /m 修饰符:因为您不使用它们修改其行为的元字符(分别为 . 和 ^/$ 对) ,他们什么都不做——货物崇拜。

    【讨论】:

      【解决方案3】:

      为什么要添加/m?你是不是想在网上分手?要使用/m 做到这一点,您需要在正则表达式中使用^ 或$:

      my @lines = split /^/m, $big_string;
      

      但是,如果您想将大字符串视为行,只需打开对标量的引用的文件句柄:

      open my $string_fh, '<', \ $big_string;
      while( <$string_fh> ) {
          ... process a line
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-22
        • 1970-01-01
        • 2022-01-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多