Соответствует ли модификатор регулярного выражения Perl /m в Windows по-разному?

Следующие операторы Perl ведут себя одинаково на машинах Unixish. Они ведут себя по-разному в Windows? Если да, то из-за магии\n?

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

Я получил сбой на одном моих модулей CPAN из дымового тестера Win32. Похоже, это проблема \r\n против \n. Одно изменение, которое я недавно сделал, заключалось в добавлении //m к моим регулярным выражениям.


person Chris Dolan    schedule 18.10.2008    source источник


Ответы (3)


Для этих регулярных выражений:

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

И /m, и /s бессмысленны.

  • /s: также делает . совпадающим с \n. Ваше регулярное выражение не содержит .
  • /m: совмещает ^ и $ рядом со встроенным \n в строке. Ваше регулярное выражение не содержит ни ^, ни $, ни их синонимов.

Что возможно, так это то, что если ваш дескриптор ввода (сокет?) Работает в текстовом режиме, символы \r (\015) будут удалены в Windows.

Так что делать? Я предлагаю сделать \015 символов необязательными и разделить их на

/\015?\012/

Нет необходимости в /m, /s или даже в начале m//. Это просто карго-культ.

person bart    schedule 18.10.2008
comment
АРХ! Я думаю, что вы правы, и я был на неправильном пути с модификаторами регулярных выражений. Я использую `` для получения входных данных от подпроцесса и никогда не думал беспокоиться о binmode... - person Chris Dolan; 19.10.2008

Нет никакой магии \n. И \n, и \r всегда означают ровно один символ, а на всех платформах, основанных на ASCII, это \cJ и \cM соответственно. (Исключениями являются платформы EBCDIC (по понятным причинам) и MacOS Classic (где \n и \r означают \cM).)

Магия, которая происходит в Windows, заключается в том, что при выполнении ввода-вывода через дескриптор файла, помеченный как находящийся в текстовом режиме, \r\n преобразуется в \n при чтении и наоборот при записи. (Кроме того, \cZ означает конец файла — сюрприз!) Это делается на уровне библиотеки времени выполнения C.

Вам нужно binmode сокет, чтобы это исправить.

Вы также должны удалить модификаторы /s и /m из своего шаблона: поскольку вы не используете метасимволы, поведение которых они изменяют (. и пара ^/$ соответственно), они ничего не делают — карго-культ.

person Aristotle Pagaltzis    schedule 18.10.2008

Почему вы добавили /m? Вы пытаетесь разделить на линии? Чтобы сделать это с /m, вам нужно использовать ^ или $ в регулярном выражении:

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

Однако, если вы хотите обрабатывать большую строку как строку, просто откройте дескриптор файла со ссылкой на скаляр:

open my $string_fh, '<', \ $big_string;
while( <$string_fh> ) {
    ... process a line
    }
person brian d foy    schedule 18.10.2008