¿El modificador de expresión regular de Perl / m coincide de manera diferente en Windows?
Pregunta
Las siguientes declaraciones Perl se comportan de manera idéntica en máquinas Unixish. ¿Se comportan de manera diferente en Windows? Si es así, ¿es por la magia \ n?
split m/\015\012/ms, $http_msg;
split m/\015\012/s, $http_msg;
Obtuve un error en uno de mis módulos CPAN de un probador de humo Win32. Parece que es un problema \ r \ n vs \ n. Uno de los cambios que hice recientemente fue agregar // m a mis expresiones regulares.
Solución
Para estas expresiones regulares:
m/\015\012/ms m/\015\012/s
Ambos / m y / s no tienen sentido.
- / s: hace que
.
coincida con\ n
también. Su expresión regular no contiene.
- / m: hace que
^
y$
coincidan al lado de\ n
incrustado en la cadena. Su expresión regular no contiene^
ni$
, ni sus sinónimos.
Lo que sí es posible es que si el controlador de entrada (socket?) funciona en modo de texto, los caracteres \ r
( \ 015
) se eliminarán en Windows.
Entonces, ¿qué hacer? Sugiero que los caracteres \ 015
sean opcionales y que se dividan en contra
/\015?\012/
No es necesario para / m, / s ni siquiera para el m //
. Esos son solo cultos de carga.
Otros consejos
No hay ningún \ n
mágico. Tanto \ n
como \ r
siempre significan exactamente un carácter, y en todas las plataformas basadas en ASCII que son \ cJ
y \ cM
respectivamente. (Las excepciones son las plataformas EBCDIC (por razones obvias) y MacOS Classic (donde \ n
y \ r
significan \ cM
).)
La magia que ocurre en Windows es que cuando se hace E / S a través de un identificador de archivo que está marcado como en modo de texto, \ r \ n
se traduce a \ n al leer y viceversa al escribir. (Además, se considera que
\ cZ
significa fin de archivo: ¡sorpresa!) Esto se hace en la capa de la biblioteca en tiempo de ejecución de C.
Necesitas binmode
para corregirlo.
También debe eliminar los modificadores / s
y / m
de su patrón: ya que no utiliza los metacaracteres cuyo comportamiento modifican (.
y el par ^
/ $
, respectivamente), no hacen nada - carga de carga.
¿Por qué agregó el / m
? ¿Estás tratando de dividir en línea? Para hacer eso con / m
necesita usar ^
o $
en la expresión regular:
my @lines = split /^/m, $big_string;
Sin embargo, si desea tratar una cadena grande como líneas, simplemente abra un identificador de archivo en una referencia al escalar:
open my $string_fh, '<', \ $big_string;
while( <$string_fh> ) {
... process a line
}