Perl的/m正则表达式修饰符在Windows上匹配方式是否不同?

5
以下Perl语句在类Unix系统上表现相同。它们在Windows上的行为是否不同?如果是,是因为魔术字符\n吗?
  split m/\015\012/ms, $http_msg;
  split m/\015\012/s, $http_msg;

我从Win32烟雾测试器中得到了一个失败消息,这似乎是\r\n与\n之间的问题。我最近做出的一个更改是在我的正则表达式中添加了//m。

3个回答

12

对于以下正则表达式:

m/\015\012/ms
m/\015\012/s
/m和/s都是无意义的。
/s: 使 . 也匹配 \n 。 您的正则表达式不包含 .
/m: 使 ^ $与字符串中嵌入的 \n 相邻匹配。 您的正则表达式既没有^也没有$,也没有它们的同义词。
如果您的输入处理(套接字?)以文本模式工作,则在Windows上, \r \015 )字符将已被删除。
那么,该怎么办?我建议使\015字符可选,并对其进行拆分。

/\015?\012/

不需要使用 /m,/s 或者甚至是前导的 m//。那些只是盲从。


啊!我想你是对的,我在正则表达式修饰符方面走错了路。我正在使用 `` 从子进程获取输入,并从未考虑过二进制模式的问题... - Chris Dolan

3

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

在Windows上发生的神奇事件是,在标记为文本模式的文件句柄上进行I/O时,读取时将\r\n转换为\n,写入时将\n转换为\r\n。(还有一个惊喜,即\cZ被视为文件结束符!)这是在C运行时库层面上完成的。

您需要对套接字执行binmode以解决此问题。

您还应该从模式中删除/s/m修饰符:因为您不使用修改其行为的元字符(.^/$配对),所以它们不起作用- 这是一种无效的做法。


1
你为什么加了/m?你是想按行分割吗?如果要使用/m进行行分割,你需要在正则表达式中使用^$
my @lines = split /^/m, $big_string;

然而,如果您想将一个大字符串视为行,请在标量引用上打开文件句柄:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接