de / m regex modificador de correspondência de forma diferente no Windows Does Perl?
Pergunta
As seguintes declarações Perl se comportam de forma idêntica em máquinas Unixish. Será que eles se comportam de forma diferente no Windows? Se sim, é por causa da magia \ n?
split m/\015\012/ms, $http_msg;
split m/\015\012/s, $http_msg;
Eu tenho um falha em um dos meus módulos do CPAN de uma fumaça tester Win32. Parece que é uma \ r \ n vs \ n questão. Uma mudança que eu fiz recentemente foi adicionar // m aos meus expressões regulares.
Solução
Para estas expressões regulares:
m/\015\012/ms m/\015\012/s
Ambos / m / s e são insignificantes.
- / S: faz
.
jogo\n
também. Seu regex não contém.
- / m: faz
^
e combinar$
ao lado\n
incorporado na cadeia. Seu regex não contém^
nem$
, ou seus sinônimos.
O que é possível é, de fato, se o seu identificador de entrada (socket?) Funciona em modo de texto, o \r
(\015
) caracteres serão eliminados no Windows.
Então, o que fazer? Sugiro fazer o \015
caracteres opcional e dividida contra
/\015?\012/
Não há necessidade de / m, / s ou mesmo o m//
líder. Essas são culto à carga apenas.
Outras dicas
Não há \n
magia. Ambos \n
e \r
sempre significa exatamente um caractere, e em todas as plataformas baseadas em ASCII que é \cJ
e \cM
respectivamente. (As exceções são plataformas EBCDIC (por razões óbvias) e MacOS clássico (onde \n
e \r
tanto \cM
média).)
A mágica que acontece no Windows é que ao fazer I / O por meio de um identificador de arquivo que está marcado como estando em modo texto, \r\n
é traduzido para \n
após a leitura e vice-versa sobre a escrita. (Além disso, \cZ
é tomado para significar fim-de-arquivo - surpresa). Isto é feito na camada de biblioteca C tempo de execução
Você precisa binmode
sua tomada para corrigir isso.
Você também deve remover os modificadores /s
e /m
de seu padrão: desde que você não use os meta-caracteres cujo comportamento eles modificam (.
eo par ^
/ $
, respectivamente), eles não fazem nada - culto da carga
Por que você adicione o /m
? Você está tentando dividir em linha? Para fazer isso com /m
você precisa usar ^
ou $
no regex:
my @lines = split /^/m, $big_string;
No entanto, se você quiser tratar uma grande cadeia como linhas, basta abrir uma filehandle em uma referência ao escalar:
open my $string_fh, '<', \ $big_string;
while( <$string_fh> ) {
... process a line
}