Regulärer Ausdruck, um die Grenze zwischen verschiedenen Unicode-Skripten zu erreichen

8

Motoren mit regulärem Ausdruck haben ein Konzept von Übereinstimmungen mit "null Breite", von denen einige nützlich sind, um Kanten von Wörtern zu finden:

  • \b - in den meisten Engines vorhanden, um eine beliebige Grenze zwischen Wort- und Nicht-Wort-Zeichen zu finden
  • \< und \> - in Vim vorhanden , um nur die Grenze am Anfang eines Wortes bzw. am Ende eines Wortes zu finden.

Ein neueres Konzept in einigen regulären Ausdrucksmaschinen sind Unicode-Klassen. Eine solche Klasse ist ein Skript, das lateinisch, griechisch, kyrillisch usw. unterscheiden kann. Diese Beispiele sind alle gleichwertig und entsprechen jedem Zeichen des griechischen Schriftsystems:

  • \p{greek}
  • \p{script=greek}
  • \p{script:greek}
  • [:script=greek:]
  • [:script:greek:]

Aber bis jetzt konnte ich beim Lesen von Quellen über reguläre Ausdrücke und Unicode nicht feststellen, ob es einen standardmäßigen oder nicht standardisierten Weg gibt, um eine Null-Breiten-Übereinstimmung zu erreichen, bei der ein Skript endet und ein anderes beginnt.

>

In der Zeichenfolge παν語 würde eine Übereinstimmung zwischen den Zeichen ν und bestehen, genauso wie \b und \< genau vor dem Zeichen π übereinstimmen würden.

Nun für dieses Beispiel könnte ich etwas zusammen hacken basierend auf der Suche nach \p{Greek} gefolgt von \p{Han} , und ich könnte sogar etwas zusammen hacken basierend auf allen möglichen Kombinationen von zwei Unicode-Skriptnamen.

Aber dies wäre keine deterministische Lösung, da mit jeder Version neue Skripte zu Unicode hinzugefügt werden. Gibt es eine zukunftssichere Möglichkeit, dies auszudrücken? Oder gibt es einen Vorschlag, es hinzuzufügen?

    
hippietrail 11.05.2013, 01:39
quelle

1 Antwort

3

BEARBEITEN: Ich habe gerade bemerkt, dass Sie nicht angegeben haben, welche Mustersprache Sie verwenden. Nun, ich hoffe, dass eine Perl-Lösung für Sie arbeiten wird, da die erforderlichen Mechanismen in jeder anderen Sprache sehr schwierig sein werden. Plus, wenn Sie Pattern-Matching mit Unicode machen, ist Perl wirklich die beste Wahl für diese besondere Art von Arbeit.

Wenn die Variable $rx unten auf das entsprechende Muster gesetzt ist, wird dieser kleine Code-Schnipsel von Perl:

%Vor%

Erzeugt diese Ausgabe:

%Vor%

Das heißt, es zieht eine lateinische Zeichenfolge, eine griechische Zeichenfolge, eine Han-Zeichenfolge und eine andere lateinische Zeichenfolge heraus. Das ist ziemlich verdammt dicht an das, was ich denke, dass Sie wirklich brauchen.

Der Grund, warum ich das gestern nicht gepostet habe, ist, dass ich komische Kern-Dumps bekomme. Jetzt weiß ich warum.

Meine Lösung verwendet lexikalische Variablen in einem (??{...}) -Konstrukt. Stellt sich heraus, dass das vor Version 5.1.1 instabil ist, und bestenfalls nur zufällig funktioniert. Es schlägt auf v5.17.0 fehl, ist aber auf v5.18.0 RC0 und RC2 erfolgreich. Deshalb habe ich ein use v5.17.1 hinzugefügt, um sicherzustellen, dass Sie etwas neueren Datums ausführen, um diesem Ansatz zu vertrauen.

Zuerst habe ich entschieden, dass Sie eigentlich keinen Lauf des gleichen Skripttyps wollen; Sie wollten einen Lauf des gleichen Skripttyps plus Common und Inherited. Andernfalls werden Sie durch Interpunktion, Leerzeichen und Ziffern für Common und durch die Kombination von Zeichen für Inherited verwirrt. Ich glaube wirklich nicht, dass du willst, dass diese deinen Lauf von "demselben Skript" unterbrechen, aber wenn du es tust, ist es einfach, damit aufzuhören, diese zu betrachten.

Wir suchen also nach dem ersten Zeichen, das einen anderen Skripttyp als Common oder Inherited hat. Darüber hinaus extrahieren wir daraus, was dieser Skripttyp eigentlich ist, und verwenden diese Informationen, um ein neues Muster zu konstruieren, das aus einer beliebigen Anzahl von Zeichen besteht, deren Skripttyp entweder Common, Inherited oder der gerade gefundene und gespeicherte Skripttyp ist. Dann bewerten wir das neue Muster und fahren fort.

Hey, ich sagte es war haarig, nicht wahr?

In dem Programm, das ich gerade zeigen werde, habe ich einige auskommentierte Debugging-Anweisungen hinterlassen, die zeigen, was es gerade macht. Wenn Sie sie auskommentieren, erhalten Sie diese Ausgabe für den letzten Durchlauf, was Ihnen helfen sollte, den Ansatz zu verstehen:

%Vor%

Und hier ist endlich der große haarige Deal:

%Vor%

Ja, es sollte ein besserer Weg sein. Ich denke nicht, dass es noch gibt.

Also, jetzt, viel Spaß.

    
tchrist 14.05.2013, 00:14
quelle