Readers: 15
[Fri Sep 20 11:27:16 2019] index.pl: Wide character in print at /usr/lib/x86_64-linux-gnu/perl5/5.26/Template.pm line 167.
2019-09-20T11:54:58 rostiAbhelfe: Vor der print-Ausgabe die Kodierung ausschalten. Am Einfachsten mit use bytes;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
use strict; use warnings; use JSON; $, = "\n"; print keys %INC; XSLoader.pm warnings/register.pm C:/Perl/site/lib/sitecustomize.pl List/Util.pm unicore/lib/Perl/_PerlIDS.pl unicore/Heavy.pl warnings.pm utf8.pm base.pm B.pm overloading.pm Config.pm JSON.pm JSON/PP.pm bytes.pm Carp.pm Exporter/Heavy.pm Scalar/Util.pm utf8_heavy.pl strict.pm vars.pm Exporter.pm constant.pm overload.pm lib.pm
2019-09-21T11:54:54 rostiUnd ja, auch JSON lädt dieses Pragma:
2019-09-23T09:26:28 rostiDas JSON Modul ist eher ein sehr schlechte Beispiel dafür wie man mit utf8kodierten Strings umzugehen hat. Denn genau diese hier beschriebene Fehlermeldung tritt bei der Verwendung dieses Moduls auf. Weil man da offensichtlich auch vergessen hat die Kodierung vor der Ausgabe auf STDOUT auszuschalten.
print JSON::encode_json( {amt => '3€'} );
2019-09-23T09:51:25 rostiCode (perl): (dl )print JSON::encode_json( {amt => '3€'} );
Gibt bei mir eine falsche Bytesequenz aus. Guck mal was Deine Version macht.
2019-09-23T09:51:25 rostiIm Übrigen ist JSON ein sog. Serializer der dazu gedacht ist, komplexe Datenstrukturen transportfähig zu machen und zwar als Bytesequenz. Wobei Transportfähig heißt, STDOU u.a. beliebige Handles. Und Bytesweuenzen selbst kennen keine Kodierung.
2019-09-23T09:51:25 rostiIm Übrigen ist JSON ein sog. Serializer der dazu gedacht ist, komplexe Datenstrukturen transportfähig zu machen und zwar als Bytesequenz. Wobei Transportfähig heißt, STDOU u.a. beliebige Handles. Und Bytesweuenzen selbst kennen keine Kodierung.
Quoteyou should use "encode_json" (supposed that JSON data are encoded
in UTF-8).
Quote..that JSON data are decoded in UTF-8)
QuoteBecause the bytes pragma breaks encapsulation (i.e. it exposes the innards of how the perl executable currently happens to store a string), the byte values that result are in an unspecified encoding.
2019-09-23T09:47:02 rostiQuoteNein, ich möchte nicht genau diese Bytesequenz ausgeben.
Doch das möchtest Du. Weil auf STDOUT grundsätzlich nur Bytesequenzen auszugeben sind.
MFG
QuoteIch möchte eine Bytesequenz ausgeben, nicht aber genau diese.
QuoteSorry, jetzt ists genug getrollt.
2019-09-23T13:04:43 rostiMeine Frage ist noch offen: Warum wird von use bytes; abgeraten!?
MFG
2019-09-23T14:52:45 rostiäußerst unproduktiv […] viel effizienter
QuoteMach dich nicht lächerlich.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
use Benchmark qw(:all); use Encode; my $chr = pack "U", 0x20AC; cmpthese(1000000, { 'Encode' => sub{ my $len = length encode_utf8($chr); my $bin = pack("N", $len).encode_utf8($chr); }, 'uBytes' => sub{ use bytes; my $bin = pack("N", length $chr).$chr; }, }); Rate Encode uBytes Encode 204499/s -- -87% uBytes 1524390/s 645% --
2019-09-23T15:25:30 rostimach ein Benchmark.
2019-09-23T09:40:55 pqNein, ich möchte nicht genau diese Bytesequenz ausgeben.
Ich weiss ja nicht, was in der Variable drinsteht, das war ja nur ein Beispiel.
Ich möchte den Inhalt einer Variable utf8-kodiert ausgeben.
Du hast meine Frage nicht beantwortet.
haj dagegen schon.
2019-09-23T08:59:30 pqSagen wir, hier ist der auszugebende Text: my $text = chr(0xC9);
Er liegt in einer perl-internen Kodierung vor.
2019-09-23T08:59:30 pqNun möchte ich den Text als UTF-8 kodiert ausgeben.
Was ist richtig?
use bytes; print $text;
oder
print Encode::encode_utf8($text);
2019-09-23T09:45:00 rostiDa können wir mal sehen wie verwirrend das ist was Perl macht. Mein Perl 6.16.3 jedenfalls betrachtet das Argument von chr() als Codepoint und nicht als Bytesequenz.
2019-09-23T09:45:00 rostiSo erzeugt my $c = chr 0xC9; eine utf8kodierte Zeichenkette genauso wie das pack "U", 0xC9; tut. Beide Zeichenketten sind gleich:
QuoteDass ein É innerhalb von Perl zwei verschiedene Darstellungen haben kann, braucht den Perl-Programmierer nicht zu kümmern.
2019-09-23T13:11:27 rostiVor allem wenn es um die Ausgabe geht, sollte man schon wissen ob perlintern eine bytesequenz vorliegt oder eine Zeichenkette mit einer bestimmten Kodierung.
QuoteDas zu wissen ist unnötig bis irreführend.
2019-09-23T14:57:57 rostiDas ist falsch. So etwas wie eine undefinierte Kodierung kann es nicht geben. (Es mag undokumentierte Kodierungen geben, aber die Definition ergibt sich de facto durch den Programmcode.)Wenn dieses Zeichen mit chr 0xC9 erzeugt wird ist die Kodierung undefiniert! Siehe perldoc -f chr
QuoteDas ist falsch. So etwas wie eine undefinierte Kodierung kann es nicht geben. (Es mag undokumentierte Kodierungen geben, aber die Definition ergibt sich de facto durch den Programmcode.)
QuoteNote that characters from 128 to 255 (inclusive) are by default
internally not encoded as UTF-8
2019-09-23T15:21:16 rostiWelche Kodierung meinst Du, liegt dann vor!?
2019-09-24T06:40:34 Daxim2019-09-23T15:21:16 rostiWelche Kodierung meinst Du, liegt dann vor!?
Das habe ich doch geschrieben: Latin1. Mit deiner Auffassungsgabe ist es nicht soweit her, oder? Nicht immer nur halb lesen/halb ignorieren, dann klappt es auch mit dem Verständnis.
1 2 3 4
use Encode qw(:all); my $c = chr 0xC9; # 1 Byte haben wir from_to($c ,'Latin1', 'utf-8'); # ergibt nun 2 Bytes print $c; # diese 2 Bytes ausgeben
2019-10-04T07:29:00 rostiPS: Wenn das mit chr(0xC9) erzeugte Byte ein Zeichen mit einer bestimmten Kodierung wäre, würden Stringfunktionen wie uc() und lc() funktionieren. Tatsächlich ist das nicht der Fall.
1 2 3 4 5 6
use 5.020; use charnames ':all'; my $c = chr 0xc9; say charnames::viacode(ord $c); # LATIN CAPITAL LETTER E WITH ACUTE say charnames::viacode(ord lc $c); # LATIN SMALL LETTER E WITH ACUTE
2019-10-05T05:45:50 rostiUnd auf die Idee use 'die Version die ich ohnhin habe' muss man erstmal kommen.
1 2 3 4 5 6 7
use 5.010; my $c = chr 0xC9; print lc $c, $c; # É É use 5.011; $c = chr 0xC9; print lc $c, $c; # é É
2019-10-05T07:52:25 rostiPS: Die 5.10 Features kenne ich. Hab ich noch nie gebraucht. Meine Alternative zu say:
Ging schon immer. Siehe perldoc perlvar.
2019-10-05T05:45:50 rostiFunktioniert mit meiner Version v5.16.3 noch nicht!
Edit: Ahh, use 5.016; dann gehts. Interessant.
2019-10-05T05:45:50 rostiDas ist richtig, aber für Deine Behauptung, lc() würde nicht funktionieren, irrelevant.PS: Das mit my $c = chr 0xC9; erzeugte Zeichen LATIN CAPITAL LETTER E WITH ACUTE ist übrigens nicht UTF-8 kodiert, nur als Hinweis für diejenigen die Unicode gerne mit UTF-8 verwechseln. Auch in ISO-8859-1 heißt das Zeichen so.
2019-10-05T05:45:50 rostiUnd auf die Idee use 'die Version die ich ohnhin habe' muss man erstmal kommen.
.
Quote, da ist es schon OK dafür auf einem 5.16.3 zu entwickeln.This is perl 5, version 12, subversion 4 (v5.12.4) built for x86_64-linux
1 2 3 4 5 6 7 8
#!/usr/bin/perl use strict; use warnings; my $c = chr 0xC9; print "Content-Type: text/plain; Charset=ISO-8859-5\n\n $c"; # Щ
$c = pack "UU", 0xC9, 0x20AC;
2019-10-05T11:42:11 rostiMein Provider bietet mirQuote, da ist es schon OK dafür auf einem 5.16.3 zu entwickeln.This is perl 5, version 12, subversion 4 (v5.12.4) built for x86_64-linux
2019-10-05T11:42:11 rostiUnd in meiner beruflichen Praxis musste ich mit der Abwärtskompatibilität sogar noch weiter runter gehen. So ist mein Framework abwärtskompatibel bis 5.6.1, abgesehen davon daß es auch in C und PHP 5.3.0 funktioniert.
2019-10-05T11:42:11 rostiEmpfehlungen richten sich stets nach Erfordernissen und dem was verfügbar ist.
2019-10-05T11:42:11 rostiUnd was den Umgang mit der Zeichenkodierung betrifft, habe ich in den letzten Firmen wo ich angestellt war gesehen wie man es besser nicht machen sollte. Z.B. sämtliche Bytesequenzen die über CGI/1.1 reinkommen in UTF-8-kodierte Zeichen umwandeln obwohl man zum Insert nach MySQL die Kodierung gar nicht braucht und von daher die Kodierung wieder ausschalten muss.
2019-10-05T11:42:11 rostiÜbrigens ist Latin1 auch nur eine Annahme was 0xC9 betrifft. charname LATIN CAPITAL LETTER E WITH ACUTE stimmt nämlich nur, wenn 0xC9 als Codepoint angenommen wird. Als Byte hingegen kann C9 auch ein ganz anderes Zeichen sein wenn man eine andere Kodierung annimmt:
Code (perl): (dl )1 2 3 4 5 6 7 8#!/usr/bin/perl use strict; use warnings; my $c = chr 0xC9; print "Content-Type: text/plain; Charset=ISO-8859-5\n\n $c"; # Щ
2019-10-05T11:42:11 rostiMeine Empfehlung: Zum Erzeugen utf8kodierter Zeichen Finger weg von der chr()-Funktion! Besser ist:
Code (perl): (dl )$c = pack "UU", 0xC9, 0x20AC;
weil das die utf8kodierten Zeichen direkt anhand des Codepoint erzeugt.
$c = "\x{C9}\x{20ac}"
2019-10-05T11:42:11 rostiIm Übrigen habe ich geschriebe daß lc() und uc() nur mit kodierten Zeichen funktionieren. Mit Bytes hingegen funktionieren lc() und uc() nicht. Darüber müssen wir nicht streiten. Der von Dir gezeigte Code bestätigt ja diesen Fakt!
.
QuoteDie Doku zu bytes sagt: "Use of this module for anything other than debugging purposes is strongly discouraged.".
1 2 3
use Carp "cluck"; # Am Anfang des Programms setzen $SIG{__WARN__}=sub { cluck @_ };
123[% x %]456
1 2 3 4 5 6 7
use utf8; use Template qw(); my $template = Template->new; $template->process('foo.tmpl', { x => '☺' }); __END__ Wide character in print at …/lib/site_perl/5.30.0/x86_64-linux-thread-multi-ld/Template.pm line 167. 123☺456
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
use utf8; use Template qw(); use Template::Constants qw(DEBUG_PROVIDER); my $template = Template->new(DEBUG => DEBUG_PROVIDER); $template->process('foo.tmpl', { x => '☺' }); __END__ [Template::Provider] creating cache of unlimited slots for [ . ] [Template::Provider] _fetch_path(foo.tmpl) [Template::Provider] searching path: ./foo.tmpl [Template::Provider] _fetch(./foo.tmpl) [Template::Provider] _load(./foo.tmpl, foo.tmpl) [Template::Provider] _compile(HASH(0x142dc80), <no compfile>) [Template::Provider] _store(./foo.tmpl, Template::Document=HASH(0x185e268)) [Template::Provider] adding new cache entry Wide character in print at …/lib/site_perl/5.30.0/x86_64-linux-thread-multi-ld/Template.pm line 167. 123☺456
1 2
$template->process('foo.tmpl', { x => '☺' }, \*STDOUT, { binmode => ':encoding(UTF-8)' }) or die $template->error;
STDOUT->binmode(':encoding(UTF-8)');
1 2 3 4 5 6 7 8
use utf8; use Template qw(); my $template = Template->new; STDOUT->binmode(':encoding(UTF-8)'); $template->process('foo.tmpl', { x => '☺' }) or die $template->error; __END__ 123☺456
2019-09-23T10:26:47 rostiDie spannende Frage ist auch hier was Perl mit ISO-8859-1 zu tun hat. Ich würde das eher so ausdrücken, daß Perl native byteorientiert arbeitet und das heißt, daß Perl per se gar keine Kodierung kennt.
2019-09-23T10:26:47 rostiIn meiner beruflichen Praxis mit Perl habe ich schon vor 20 Jahren Bytesequenzen ausgegeben die jeder Browser einwandfrei als utf8kodiert darstellen konnte. Und das mit einen Perl dessen Unicodeunterstützung gleich null war. In dieser Zeit ist man noch nicht einmal auf die Idee gekommen, für ISO--8859-1-kodierte Zeichen /i zu schalten, was definitiv erst mit v5.8 möglich wurde also Encode ins Spiel kam. Und seither gibt es nur noch Missverständnisse.
MFG
QuoteDem kann ich mich nahezu anschließen: Byteorientiert ist richtig. Allerdings entspricht ein chr(0xc9) in Perl dem Pattern /\w/ als "alphanumerisch", so dass ein bisschen Kodierung in Perl doch eingebaut ist.
QuoteNote that characters from 128 to 255 (inclusive) are by default
internally not encoded as UTF-8 for backward compatibility
reasons.