Le modificateur de regex / m de Perl correspond-il différemment sous Windows?
Question
Les instructions Perl suivantes se comportent de manière identique sur les ordinateurs Unix. Est-ce qu'ils se comportent différemment sous Windows? Si oui, est-ce dû à la magie \ n?
split m/\015\012/ms, $http_msg;
split m/\015\012/s, $http_msg;
J'ai un échec sur l'un de mes modules CPAN à partir d'un testeur de fumée Win32. Cela semble être un problème \ r \ n vs \ n. Un changement que j'ai apporté récemment a été d'ajouter // m à mes expressions rationnelles.
La solution
Pour ces regex:
m/\015\012/ms m/\015\012/s
Les deux / m et / s n'ont pas de sens.
- / s: fait que
.
correspond également à\ n
. Votre regex ne contient pas.
- / m: établit une correspondance entre
^
et$
en regard de\ n
incorporé dans la chaîne. Votre regex ne contient pas^
ni$
, ni leurs synonymes.
Ce qui est possible est en effet si votre descripteur d’entrée (socket?) fonctionne en mode texte, les caractères \ r
( \ 015
) auront été supprimés sous Windows.
Alors, que faire? Je suggère de rendre les caractères \ 015
facultatifs et de les scinder en fonction de
/\015?\012/
Pas besoin de / m, / s ou même du premier m //
. Ce ne sont que culte du fret.
Autres conseils
Il n'y a pas de magie \ n
. \ n
et \ r
signifient toujours exactement un caractère, et sur toutes les plates-formes basées sur ASCII, \ cJ
et \ cM
respectivement. (Les exceptions sont les plates-formes EBCDIC (pour des raisons évidentes) et MacOS Classic (où \ n
et \ r
signifient tous les deux \ cM
).)
La magie qui se produit sous Windows est que, lorsque vous effectuez des E / S via un descripteur de fichier marqué comme étant en mode texte, \ r \ n
est traduit en \ n
lors de la lecture et vice versa lors de l'écriture. (En outre, \ cZ
signifie "surprise de fin de fichier"!). Ceci est effectué au niveau de la couche de la bibliothèque d'exécution C.
Vous devez binmode
votre socket pour y remédier.
Vous devez également supprimer les modificateurs / s
et / m
de votre modèle: puisque vous n'utilisez pas les méta-caractères dont ils modifient le comportement (.
et la paire ^
/ $
, respectivement), ils ne font rien & # 8211; culte de la cargaison.
Pourquoi avez-vous ajouté le / m
? Est-ce que vous essayez de vous séparer en ligne? Pour faire cela avec / m
, vous devez utiliser ^
ou $
dans la regex:
my @lines = split /^/m, $big_string;
Cependant, si vous souhaitez traiter une grosse chaîne comme des lignes, ouvrez simplement un descripteur de fichier sur une référence au scalaire:
open my $string_fh, '<', \ $big_string;
while( <$string_fh> ) {
... process a line
}