EisFuX: variable-length look-behind assertions selbst gebaut

Beitrag lesen

(Hallo|Hi(ho)|Tag) Oliver,

ich tüftelt gerade an einem Problem.
Ich habe einen String, dessen Inhalt ich bei Auftreten eines Semikolons trennen möchte. Allerdings können in dem String auch Entitities in der Form > bei denen ich natürlich nicht nach dem Semikolon trennen möchte.

Momentaner Ansatz:

my @terms = split(/(?<!&#62);/,$string);

Das funktioniert sehr gut, solange die Entität genau definiert ist. Allerdings kann man das nicht verallgemeinern zu &#.+ da Lookahead nur bei fester Länge funktioniert. Da kommt sonst die Meldung variable length not implemented.

Das Lookbehind-Assertions nicht mit variablen Längen funktionieren, ist ja nun geklärt ...

Hat vielleicht jemand einen Lösungsansatz - eventuell auch ganz andere Herangehensweise?

Schreib dir eine eigene Funktion, die $string nach Semikola und Entitäten abklappert, aber nur bei allein stehenden Semikola abschnippelt ...

Wenn es denn aber unbedingt mit split() funktionieren muss, versuch mal das hier:

  
my $string = 'Test; Bla &thetasym; Blubb; Fred &amp; Barney; Meyer & Co.; nicht &#8230; und so weiter';  
my @terms;  
  
@terms = split /(?<!&.{2})(?<!&.{3})(?<!&.{4})(?<!&.{5})(?<!&.{6})(?<!&.{7})(?<!&.{8});/, $string;  

Sieht zwar nicht sehr elegant aus, dürfte aber seinen Zweck erfüllen. Schließlich kann man mehrere Assertions ohne weiteres nebeneinander setzen -- sie werden quasi UND-verknüpft.

Dieses  Konstrukt deckt Entitäten ab, die in folgenden Bereichen liegen:

  
# kürzeste  
# &lt;  
# &#1;  
  
# längstmögliche  
# &thetasym; # eine längere CCE kennt mein Opera nicht ;-)  
# &#9999999;  
# &#xFFFFFF;  

Zusätzlich zu beachten wäre, dass ...

... keine freifliegenden "&"s im Text vorkommen dürfen, sonst passiert sowas wie oben bei "Meyer & Co;" angegeben.

... die RegEx-Engine dann natürlich bei jedem gefundenen Semikolon bis zu 7 Assertions prüfen muss.

Wenn du im Ausgangstext nur numerische Character References hast, kannst du die Suchmuster auch entsprechend anpassen:

  
  
/(?<!&#.{2})(?<!&#.{3})(?<!&#.{4})(?<!&#.{5})(?<!&#.{6})(?<!&#.{7});/  

MffG
EisFuX