Различается ли в Windows модификатор / m регулярного выражения Perl? - PullRequest
5 голосов
/ 18 октября 2008

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

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

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

Ответы [ 3 ]

12 голосов
/ 18 октября 2008

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

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

Оба / м и / с не имеют смысла.

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

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

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

/\015?\012/

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

3 голосов
/ 18 октября 2008

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

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

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

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

1 голос
/ 18 октября 2008

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

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

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

open my $string_fh, '<', \ $big_string;
while( <$string_fh> ) {
    ... process a line
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...