Ich habe zwei Json-Dateien, die von verschiedenen Betriebssystemen stammen.
Beide Dateien sind in UTF-8
codiert und enthalten UTF-8
encoded filenames
.
Eine Datei kommt von OS X und der Dateiname ist in NFD-Form: ( od -bc
)
Die zweite enthält den gleichen Dateinamen, aber in NFC-Form:
%Vor% Wie ich erfahren habe, wird dies als "andere Normalisierung" bezeichnet, und es gibt ein CPAN-Modul Unicode::Normalize
, um es zu handhaben.
Ich lese beide Dateien mit dem nächsten:
%Vor% Die read_file stammt von File::Slurp
und decode_json von JSON::XS
.
Wenn Sie den JSON in Perl-Struktur lesen, kommt der Dateiname aus einer JSON-Datei in key
position und aus der zweiten Datei in values
. Ich muss suchen, wenn der Hash key
aus dem 1. Hash gleichwertig zu einem value
aus dem zweiten Hash ist, also müssen Sie sicherstellen, dass sie "binär" identisch sind.
Versuchte die nächste:
%Vor%und
%Vor%erzeugt für mich die gleiche Ausgabe.
Jetzt die Fragen:
$hashrefs
? oder muss nach dem decode_json
etwas wie bei beiden Hashes laufen?
Kurz gesagt:
$href
zu erhalten? Es ist möglich, etwas schöner zu erreichen, indem Sie NFD
für jedes key
value
explizit ausführen und eine weitere NFD-normalisierte (große) Kopie der Hashes erstellen? Einige Hinweise, Vorschläge - bitte ...
Weil mein Englisch sehr schlecht ist, hier ist eine Simulation des Problems
%Vor%Bei der Suche nach der richtigen Lösung für Ihre Frage entdeckte ich: Die Software ist c * rp :) Siehe: Ссылка .
Wie auch immer, die Lösung für Ihre spezielle Frage gefunden - Wie liest man json mit Dateinamen unabhängig von der Normalisierung:
anstelle von Ihrem:
%Vor%Verwenden Sie die nächste:
%Vor% Dies sollte (zumindest hoffe ich) sicherstellen, dass die Dekomposition den JSON-Inhalt verwendet, die NFC
konvertiert sie in eine vorkompilierte Version und die JSON: XS liest sie korrekt in dieselbe interne Perlstruktur.
So druckt Ihr Beispiel:
%Vor% ohne die $json
Die Idee kommt von Joseph Myers und Nemo;)
Vielleicht geben mehr erfahrene Programmierer mehr Hinweise.
Auch wenn es im Moment wichtig sein könnte, nur ein paar Dateinamen in die gleiche Normalisierung für den Vergleich zu konvertieren, können andere unerwartete Probleme fast überall auftreten, wenn JSON-Daten eine andere Normalisierung haben.
Mein Vorschlag ist also, die gesamte Eingabe aus beiden Quellen als ersten Schritt vor dem Parsen zu normalisieren (d. h. gleichzeitig mit dem Lesen der Datei und vor decode_json
). Dies sollte keine Ihrer JSON-Strukturen beschädigen, da diese durch ASCII-Zeichen getrennt sind. Dann sollte Ihr existierender Perl-Code in der Lage sein blind anzunehmen, dass alle UTF8-Zeichen die gleiche Normalisierung haben.
Um diesen Vorgang etwas schneller zu machen (er sollte schon sehr schnell sein, da das Modul schnelle XS-Prozeduren verwendet), können Sie herausfinden, ob eine der beiden Datendateien bereits in einer bestimmten Normalisierungsform vorliegt, und diese Datei dann belassen unverändert und konvertiert die andere Datei in diese Form.
Zum Beispiel:
%Vor%Natürlich müssten Sie jetzt in der Entwicklungszeit experimentieren, um zu sehen, ob die eine oder die andere der Eingabedateien bereits in einer normalisierten Form vorliegt, und dann würden Sie in Ihrer endgültigen Version des Codes nicht mehr eine benötigen bedingte Anweisung, sondern einfach die andere Eingabedatei in die gleiche normalisierte Form konvertieren.
Beachten Sie auch, dass die Ausgabe in NFC-Form vorgeschlagen wird (wenn Ihr Programm eine Ausgabe erzeugt, die später gespeichert und verwendet wird). Siehe hier zum Beispiel: Ссылка
Hm. Ich kann Ihnen keine bessere "Programmier" -Lösung empfehlen. Aber warum läuft einfach nicht
%Vor%und jetzt kann Ihr Skript beide lesen und verwenden, weil sie beide in der gleichen Normalisierung sind? Anstatt also nach der Programmierlösung innerhalb Ihres Skripts zu suchen, lösen Sie das Problem, bevor Sie das Skript aufrufen. (Der zweite Befehl ist nicht notwendig - einfache Konvertierung auf Dateiebene. Sicher ist einfacher, als Datenstrukturen zu durchlaufen ...