2016-03-31 8 views
1

Ich versuche, das folgende Muster zu entsprechen und ein Array erstellen, wie unten beschrieben:hinzufügen Regex paßt zu bidimensional Array im Namen ihrer Position

  • letter 'c' followed by digit
  • letter 'c' followed by digit dash digit
  • digit may be followed by an other digit enclosed in square parentheses []

Muster sind durch Komma getrennt.

Beispiel:

c2,c3-5,c6[2],c8[4]-10,c14-21[5] 

Diese Zahlen beziehen sich auf den Absätzen der Artikel von Gesetzen und wo es einen Strich bedeutet dies, dass eine Reihe von Absätzen ist.

So zum Beispiel:

c3-5 = paragraphs from 3 to 5 

Mit der folgenden regex ich mithalten kann und trennen Sie die Zahlen:

(\d+(\[\d+\])?-\d+(\[\d+\])?)|(\d+(\[\d+\])?) 

https://regex101.com/r/iQ2pQ3/1

Aber effektiv nutzen diese Zahlen Ich versuche, Erstellen - ohne Erfolg - ein Array mit der folgenden Struktur:

Array 
(
    [0] => Array 
    (
     [start] => 2 
     [end]=> 
    ) 
    [1] => Array 
    (
     [start] => 3 
     [end] => 5 
    ) 
    [2] => Array 
    (
     [start] => 6[2] 
     [end] => 
    ) 
    [3] => Array 
    (
     [start] => 8[4] 
     [end] => 10 
    ) 
    [4] => Array 
    (
     [start] => 14 
     [end] => 21[5] 
    ) 
) 

Sie können sehen, dass einzelne Spiele auf das Array mit dem Schlüssel [start], hinzugefügt werden, wenn es ein Bindestrich (ein Bereich) die erste Ziffer mit der Taste [start] und die zweite mit dem Schlüssel [end] hinzugefügt.

Die einzige Art, wie ich dachte, dass ich es zu ersten explode durch Komma der Zeichenfolge aus arbeiten konnte und dann einen regulären Ausdruck auf den einzelnen explodierten Strings verwenden. Selbst wenn man nicht weiß, wie man ein Array wie das obige baut.

Gibt es eine bessere (kompaktere und elegantere) Methode?

Antwort

1

Verwenden Sie die folgende regex-basierte Lösung (siehe demo):

$re = '~c(?<start>\d+(?:\[\d+])?)(?:-(?<end>(?&start)?))?~'; 
$str = "c2,c3-5,c6[2],c8[4]-10,c14-21[5]"; 
preg_match_all($re, $str, $matches); 
$res = array_map(function($ms, $me) { 
    return array("start" => $ms, "end" => $me); 
}, $matches["start"], $matches["end"]); 
print_r($res); 

Die Regex anubhava der ähnlich ist, aber ich verkürzt es mit Hilfe eines benannten Unterprogramm-Aufruf (das tatsächlich recurses, resuses, die start Unter-Pattern):

c(?<start>\d+(?:\[\d+])?)(?:-(?<end>(?&start)?))? 

die regex demo Siehe, hier ist seine Erklärung:

  • c - ein Literal c
  • (?<start>\d+(?:\[\d+])?) - (Gruppe "Start") ein obligatorischer Submuster, \d+ Streichhölzer 1+ Ziffern, die wahlweise gefolgt mit 1 Auftreten von : befolgt mit [ + Ziffern + ]
  • (?:-(?<end>(?&start)?))? - 1 oder 0 (optional) Sequenz - gefolgt von der "Start" -Gruppe (der Wert wird in die "End" -Gruppe gelegt).
+1

Fantastisch! Ich wusste nicht, dass Gruppen benannt werden können. Sehr gute und nützliche Erklärung. – Nicero

0

Sie können Ihre Regex dies ändern auch leer Spiele zu erfassen:

c(?P<start>\d+(?:\[\d+\])?)-?(?P<end>\d+(?:\[\d+\])?|)(?=,|$) 

RegEx Demo

(?P<end>\d+(?:\[\d+\])?|) garantiert, dass wir auch leer Treffer in end Gruppe erfassen.

Verwandte Themen