char c = 'x';
string s = "xyz";
et en Java String
s = "xyz";
(la majuscule de String
est
significative)'x'
, constante de type
caractère, de "x"
, constante de chaîne de longueur 1.'il est $h heures'
en Perl ou en PHP
représente la même chaîne de longueur 16 "
il est $h heures
"
en Java
ou en C++.$
') apparaît dans
la chaîne, $h
vaut 17, alors en Perl comme en PHP la
chaîne "
il est $h heures
"
représente en fait 'il est 17 heures'
charAt(k)
censée renvoyer le k-1ème
caractère d'une chaîne, renvoie en fait une chaîne de longueur 1 :"xyz".charAt(1) == "y"
)"Il me dit : "Aglaé !""
ne fonctionne
manifestement
pas."Il me dit : 'Aglaé !'"
\
'
(appelé en français la controblique et en anglais backslash),
qui indique, d'une manière générale, que le caractère qui le suit
immédiatement doit recevoir un traitement spécial."Il me dit : \"Aglaé !\""
\n
ou le retour-chariot \r
, '\0'
.\ule-numéro-Unicode-en-hexadécimal
'
en Java (guillemets simples pour un caractère isolé)"
\ule-numéro-Unicode-en-hexadécimal
"
en Javascript (guillemets doubles car Javascript ne connaît que les
chaînes)\x{le-numéro-Unicode-en-hexadécimal}
"
en Perl (guillemets simples ou doubles suivant le cas)use
utf8
".\x{le-numéro-Unicode-en-hexadécimal}
"\x{4E0D}\x{540C}
' (avec les guillemets
simples ou doubles) est l'écriture Perl-ASCII du mot chinois "不同"
(en pinyin bùtóng
= différent)use
utf8
", ASCII |
UTF8 |
use strict; ($$){ # 2 noms de fichiers my ($fichin, $fichout) = @_;
open(ENTREE, "<:utf8", "$fichin"); open(SORTIE, ">:utf8",
"$fichout"); #***************************************
#***************************************
my @tablignes =
<ENTREE>;
|
use strict; sub extrmotif ($$){ # 2 noms
de fichiers my ($fichin, $fichout) = @_;
open(ENTREE, "<:utf8", "$fichin"); open(SORTIE, ">:utf8",
"$fichout"); #*************************************** my $er = '不同'; #***************************************
my @tablignes =
<ENTREE>;
|
U+4e0d
'不'.$er = '\x{4e0d}\p{Han}';
use utf8
" : $er = '不
\p{Han}';
Si vous souhaitez écrire une classe de caractères comme\p{Han}
dans une chaîne évaluée (entre guillemets doubles),
n'oubliez pas de doubler la controblique ! et d'écrire\\p{Han}
.
Explication :
Perl considère que tout caractère précédé d'une controblique est spécial, par exemple :
Liste complète ici.
\x
introduit un caractère donné par son numéro (en Java et en Javascript, c'est\u
qui joue ce rôle),\a
déclenche une sonnerie (bell)
\n
représente le saut de ligne, etc- et
\\
est évalué en\
simple.
Si le caractère en question ne figure pas dans la liste, Perl le transmet tel quel, et imprime un message d'avertissement.
Or\p
n'a pas de rôle spécial !
Il sera donc évalué commep
tout nu, non sans avoir provoqué une protestation :
Unrecognized escape \p passed through at monscript.pl line xxx.
Doubler la controblique aura pour effet que lors de l'évaluation le digramme\\
sera remplacé par\
simple,
et que le calcul se poursuivra avec le\p
désiré.
Donc, pour construire l'exp. reg. précédente en séquence, suivant la bonne méthode, on écrira :
my $debut = '\x{4e0d}';
my $er = "$debut\\p{Han}";
Cette observation vaut pour tous les escapes qui entrent dans la composition des exp. reg. mais ne relèvent pas de la théorie générale des chaînes en Perl. Dans le doute, il est prudent de doubler toutes les controbliques dans les chaînes évaluées !
my $er = '\p{Han}{4}|\p{Greek}+';
my $er =
'\p{BidiClass:R}+|\p{BidiClass:AL}+';
BidiClass:R
(contrairement
à ce qu'on peut lire un peu partout) BidiClass
: voyez Wikipedia. R
' ne ne vise que l'hébreu !BidiClass:AL
pour avoir aussi l'arabe, le
syriaque et le thaana (écriture en usage aux Maldives). \x{4E0D}\x{540C}
'不同
'.indirā gāndhī
'
(et réciproquement). open(ENTREE, "<:utf8", "$fichin");
open(SORTIE, ">:utf8",
"$fichout");
STDIN
et STDOUT
sont toujours
ouverts, la technique ci-dessus est inapplicable. À sa place :binmode(STDIN, ":utf8");
binmode(STDOUT, ":utf8");
évitera les avertissements "Wide
character in print..."
STDIN
ne concerne que les
octets qui sont obtenus par des ordres de lecture explicites,@ARGV
:@ARGV[0]
, @ARGV[1]
etc sont
lus comme des chaînes d'octets. decode_utf8
du module Encode
.extrmotif
de la section
précédente doive s'appliquer à des noms de fichiers non-ASCII,use Encode 'decode_utf8';
$ARGV[0] = decode_utf8($ARGV[0], 1);
$ARGV[1] = decode_utf8($ARGV[1], 1);
extrmotif($ARGV[0], $ARGV[1]);
decode_utf8
a
pour effet de provoquer un arrêt immédiat si par malheur la chaîne
d'octets est mal codée.@ARGV = map { decode_utf8($_, 1) } @ARGV;
jfp% perl extrmotif.pl ἀνέχου.txt ἀπέχου.txt
ἀνέχου.txt, ἀπέχου.txt
"Wide character in
print..."
devrait vous mettre la puce à l'oreille !
binmode(STDOUT, ":utf8");
jfp% perl extrmotif.pl ἀνέχου.txt ἀπέχου.txt
á¼Î½ÎÏοÏ
.txt, á¼ÏÎÏοÏ
.txt
\x{4E0D}\x{540C}
' (Perl)\u4e0d\u540c"
(Java ou Javascript)不同
' (HTML-XML hexa)不同
' (HTML-XML
décimal)ord
qui à un caractère quelconque c
associe son n° dans la
catalogue Unicode. ord(c)
en
hexadécimal
(le plus souvent) ou en décimal.sprintf
,
avec comme chaîne de format '%x'
pour de l'hexa, '%X'
pour de l'hexa en majuscules, ou '%d'
pour du décimal.c
--> '\x{'.sprintf('%X',
ord(c)).'}'
c
--> '\u'.sprintf('%x',
ord(c))
c
--> '&#x'.sprintf('%X',
ord(c)).';'
c
-->
'&#'.sprintf('%d',
ord(c)).';'
string2Perl0.pl
)use strict;
use warnings;
sub car2chn($){ #caractère --> chaîne
my( $c ) = @_;
return ('\x{'.sprintf('%X', ord($c)).'}');
}#car2chn
sub chn2chn($){ #chaîne --> chaîne
my( $chn ) = @_;
my @tabcar = split(//, $chn);
my $res = '';
foreach my $c ( @tabcar ){
$res .= car2chn($c)
}
return $res;
}#chn2chn
use Encode 'decode_utf8';
$ARGV[0] = decode_utf8($ARGV[0], 1);
print(chn2chn($ARGV[0]));
eg
'sub chn2chn($){ #chaîne --> chaîne
my( $chn ) = @_;
$chn =~ s/(.)/car2chn($1)/eg;
return $chn;
}#chn2chn
e
' et 'g
' permet de
réaliser une boucle "sur toutes les occurrences des sous-chaînes
filtrées par l'exp.reg.". string2Perl.pl
.不同
',
retrouver le mot chinois '不同'.chr
,
inverse de ord
: pour un entier n
donné, chr(n)
est le caractère dont n
est le n° Unicode. On a donc,
pour tout caractère c
, c
= chr(ord(c))
,
et pour tout entier n
< 1 114 112, n
= ord(chr(n))
.chr
suffit à provoquer la conversion.hex
qui effectue la conversion désirée. sub chnHex2chn($){ #chaîne --> chaîne
my( $chn ) = @_;
$chn =~ s/&#x([0-9A-F]+);/chr(hex($1))/eg;
return $chn;
}#chnHex2chn
sub chnDec2chn($){ #chaîne --> chaîne
my( $chn ) = @_;
$chn =~ s/&#(\d+);/chr($1)/eg;
return $chn;
}#chnDec2chn
"J'espère qu'il est conforme à la réglementation..."
"J'esp=C3=A8re qu'il est conforme =C3=A0 la
r=C3=A9glementation..."
"J%27esp%C3%A8re+qu%27il+est+conforme+%C3%A0+la+r%C3%A9glementation..."
%
'
et non par '=
'. +
', le guillemet simple
codé '%27
', etc.utf8::encode
utf8::encode
, dont
voici le principe :utf8::encode
, demo_encode.pl
)
use strict;
use warnings;
sub montrer($){ #chaîne
my( $chn ) = @_;
my @tab = split(//, $chn);
foreach my $c ( @tab ){
print ("$c - ".sprintf('%X',
ord($c))."\n");
}
print "-------\n";
}#montrer
sub observer($){ #chaîne
my( $chn ) = @_;
montrer($chn);
utf8::encode($chn);# Hic jacet lepus !
montrer($chn);
}#observer
binmode(STDOUT, ":utf8");
use Encode 'decode_utf8';
$ARGV[0] = decode_utf8($ARGV[0], 1);
observer($ARGV[0]);
καὶ
en UTF-8 = CEBA CEB1
E1BDB6
.jfp% perl demo_encode.pl καὶ
κ - 3BA
α - 3B1
ὶ - 1F76
-------
Î - CE
º - BA
Î - CE
± - B1
á - E1
½ - BD
¶ - B6
-------
string2QP.pl
use strict;
use warnings;
sub traiter_octet($){ #caractère d'un octet
my( $c ) = @_;
my $val = ord($c); # entier
if( $val < 128 ){ #ASCII
return chr($val);
}else{
return '='.sprintf('%X', $val);
}
}#traiter_octet
sub toQP($){ #chaîne
my( $chn ) = @_;
utf8::encode($chn);
$chn =~ s/(.)/traiter_octet($1)/eg;
return $chn;
}#observer
use Encode 'decode_utf8';
$ARGV[0] = decode_utf8($ARGV[0], 1);
print toQP($ARGV[0]);
print "\n";
jfp% perl string2QP.pl "J'espère qu'il est conforme à la
réglementation..."
J'esp=C3=A8re qu'il est conforme =C3=A0 la r=C3=A9glementation...
traiter_octet
:string2URL.pl
sub ordinaire($){ #entier
my( $val ) = @_;
return($val<128
#ASCII
&& $val !=
0x27 #simple quote
&& $val !=
0x22 #double quote
#etc
)
}#ordinaire
sub traiter_octet($){ #caractère d'un octet
my( $c ) = @_;
my $val = ord($c); # entier
if( $val == 0x20 ){
return '+';
}else{
if( ordinaire($val) ){ #ASCII non
spécial
return
chr($val);
}else{
return
'%'.sprintf('%X', $val);
}
}
}#traiter_octet
Le reste comme ci-dessus
jfp% perl string2URL.pl "J'espère qu'il est conforme à la
réglementation..."
J%27esp%C3%A8re+qu%27il+est+conforme+%C3%A0+la+r%C3%A9glementation...
utf8::decode
utf8::decode
, utf8::encode
, dont nous avons fait
nos choux gras au paragraphe précédent.decode_utf8
que nous employons pour passer une chaîne utf8 comme argument sur
la ligne de commande (ce genre de doublons est courant en Perl). utf8::encode
, son inverse utf8::decode
opère in situ et transforme son argument, remplaçant les
séquences d'un, deux, trois ou quatre caractères d'un seul octet par
les caractères ainsi codés en UTF-8 eux-mêmes.demo_encode.pl
l'appel à utf8::encode
par un appel à utf8::decode
:jfp% perl demo_decode.pl καὶ
Î - CE
º - BA
Î - CE
± - B1
á - E1
½ - BD
¶ - B6
-------
κ - 3BA
α - 3B1
ὶ - 1F76
-------
καὶ'
représente le mot grec 'καὶ' codé en UTF-8.Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: quoted-printable
sub qp2utf8($){ #chaine en quoted-printable
my ( $chn ) = @_;
my $er = '=([0-9A-F]{2})';
$chn =~s/$er/chr(hex($1))/eg;
utf8::decode($chn);
return $chn;
}#qp2utf8