Von meinen vorherigen Fragen Why under locale-pragma word characters do not match? und How to change nested quotes Ich habe gelernt, dass im Umgang mit UTF-8-Daten können Sie \w
nicht als Word-Zeichen vertrauen und Sie müssen die Unicode-Zeicheneigenschaft \p{Word}
verwenden. Jetzt bin ich in einer Situation, in der ich fand, dass Null-Wortgrenze \b
auch nicht mit UTF-8 funktioniert (mit aktiviertem Gebietsschema), aber ich fand keine Entsprechung in Unicodezeicheneigenschaften. Ich dachte, ich könnte es selbst bauen wie: (?<=\P{Word})(\p{Word}+)(?=\P{Word})
, sollte es \b(\w+)\b
entsprechen.Wie Emulation der Wortgrenze bei Verwendung von Unicode-Zeicheneigenschaften?
Im Testskript unten habe ich zwei Arrays, um zwei verschiedene Regexe zu testen. Die erste basiert auf \b
funktioniert gut, wenn das Gebietsschema nicht aktiviert ist. Um es auch mit Locales arbeiten zu lassen, schrieb ich eine andere Version mit Emulation der Grenze (?=\P{Word})
, aber es funktioniert nicht so, wie ich es erwartet hatte (ich zeige auch erwartete Ergebnisse im Skript).
Sehen Sie, was falsch ist und wie man emulierte Regex-Arbeit als erstes mit ASCII (oder ohne Gebietsschema) bekommt?
#!/usr/bin/perl
use 5.010;
use utf8::all;
use locale; # et_EE.UTF-8 in my case
$| = 1;
my @test_boundary = ( # EXPECTED RESULT:
'"abc def"', # '«abc def»'
'"abc "d e f" ghi"', # '«abc «d e f» ghi»'
'"abc "d e f""', # '«abc «d e f»»'
'"abc "d e f"', # '«abc "d e f»'
'"abc "d" "e" f"', # '«abc «d» «e» f»'
# below won't work with \b when locale enabled
'"100 Естонiï"', # '«100 Естонiï»'
'"äöõ "ä õ ü" ï"', # '«äöõ «ä õ ü» ï»'
'"äöõ "ä õ ü""', # '«äöõ «ä õ ü»»'
'"äöõ "ä õ ü"', # '«äöõ «ä õ ü»'
'"äöõ "ä" "õ" ï"', # '«äöõ «ä» «õ» ï»'
);
my @test_emulate = ( # EXPECTED RESULT:
'"100 Естонiï"', # '«100 Естонiï»'
'"äöõ "ä õ ü" ï"', # '«äöõ «ä õ ü» ï»'
'"äöõ "ä õ ü""', # '«äöõ «ä õ ü»»'
'"äöõ "ä õ ü"', # '«äöõ "ä õ ü»'
'"äöõ "ä" "õ" ï"', # '«äöõ «ä» «õ» ï»'
);
say "BOUNDARY";
for my $sentence (@test_boundary) {
my $quote_count = ($sentence =~ tr/"/"/);
for (my $i = 0 ; $i <= $quote_count ; $i += 2) {
$sentence =~ s/
"( # first qoute, start capture
[\p{Word}\.]+? # suva word-char
.*?\b[\.,?!»]*? # any char followed boundary + opt. punctuation
)" # stop capture, ending quote
/«$1»/xg; # change to fancy
}
say $sentence;
}
say "EMULATE";
for my $sentence (@test_emulate) {
my $quote_count = ($sentence =~ tr/"/"/);
for (my $i = 0 ; $i <= $quote_count ; $i += 2) {
$sentence =~ s/
"( # first qoute, start capture
[\p{Word}\.]+? # at least one word-char or point
.*?(?=\P{Word}) # any char followed boundary
[\.,?!»]*? # optional punctuation
)" # stop capture, ending quote
/«$1»/gx; # change to fancy
}
say $sentence;
}
Zuerst Sie sind falsch: '\ w' und' \ p {word} 'sind per Definition identisch. Aber zweitens, bitte, bitte, bitte *** benutze nicht das 'use locale'-Pragma. Es ist kaputt, unzuverlässig, unberechenbar und ein königlicher Schmerz im Hintern - wie Sie anscheinend entdeckt haben. Sie sollten das Modul "Unicode :: Collate :: Locale" verwenden. Du solltest wahrscheinlich auch nicht 'utf8: all' benutzen, sondern die spezifischen Dinge tun, die du willst. – tchrist
@tchrist: '\ w' und' \ p {Wort} 'können identisch definiert werden, aber sie verhalten sich unter' use locale' anders. Natürlich werde ich das Gebietsschema nicht verwenden, wenn ich jetzt anders unterwegs bin. 'utf8 :: all' verwendet meine Bedürfnisse ziemlich gut und es ist eine saubere Art, meine Absichten zu zeigen. Wenn in utf8 :: all etwas fehlt, könnten Sie es vielleicht dem Autor zeigen? –
Sie wissen nicht, was "utf8: all" tut oder nicht, was genau das Problem ist - ein Problem, das kann ich nicht durch Hinzufügen von Dingen beheben. Welche Ebene von "utf8" Warnungen erhalten Sie? Keine oder Warnung oder tödlich? Was ist mit den drei Subtypen, dem nonchar und den Surrogaten und der non_unicode? Diese Dinge sollten im Code explizit sein, damit die Leute sehen können, was sie sind. Dann gibt es das Problem des Renderns in NFD bei Eingabe und NFC bei Ausgabe; macht es das? – tchrist