Normalisierung von utf8 Dateinamen, die in JSON mit Perl gespeichert sind

8

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 )

%Vor%

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:

  • Wie einfach beide json-Dateien lesen, um dieselbe Normalisierung in beide $hashrefs ?
  • zu bekommen

oder muss nach dem decode_json etwas wie bei beiden Hashes laufen?

%Vor%

Kurz gesagt:

  • Wie lese ich verschiedene JSON-Dateien, um die gleiche Normalisierung "innerhalb" der Perl $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%     
kobame 02.07.2013, 19:19
quelle

4 Antworten

1

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

zu durchlaufen

Die Idee kommt von Joseph Myers und Nemo;)

Vielleicht geben mehr erfahrene Programmierer mehr Hinweise.

    
jm666 03.07.2013, 15:43
quelle
1

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.

%Vor%

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: Ссылка

    
Joseph Myers 02.07.2013 19:23
quelle
1

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 ...

    
Nemo 02.07.2013 20:54
quelle
-1

Anstatt die Datenstruktur manuell zu durchlaufen, lassen Sie ein Modul dies für Sie erledigen.

daxim 02.07.2013 20:22
quelle

Tags und Links