2016-04-07 10 views
2

Ich versuche, Werte von Spalten einschließlich (!) Leerer Spalten aus mehreren CSV-ähnlichen einfachen Datenspaltenfolgen zu erfassen, die durch ein Semikolon getrennt sind. Und selbst wenn ich weiß, dass Regex nicht der beste Ansatz dafür ist und explizite CSV-Parser einen besseren Job machen würden, bleibt mir nichts anderes übrig, als PRCE Regex zu verwenden, um HTML-Tabellen <td> Gruppen aus diesen Daten zu erstellen.Werte aus einer CSV-ähnlichen Zeichenfolge extrahieren, einschließlich leerer Felder mit PCRE-Regex

Das worsed Beispiel, das sollte (noch) Arbeit, sieht wie folgt aus:

;testvalue;"testvalue";"test "val"ue";test value; 

... was wörtlich wie folgt interpretiert werden:

empty | testvalue | testvalue | test "val"ue | test value | empty 

... die schließlich gerendert wird in diesen (nicht in Frage Teil):

<td>empty</td> 
<td>testvalue</td> 
<td>testvalue</td> 
<td>test"val"ue</td> 
<td>test value</td> 
<td>empty</td> 

(UPDATE wie von @anubhava gefragt)

Leider gibt es noch eine andere downer kommt mit: Das System, in dem es implementiert wird, hat eine feste Möglichkeit, die Strings zu behandeln. Es wird NUR erkannte Gruppen der Zeichenfolge erkennen und NUR ändern. Jeder andere nicht registrierte Teil der Zeichenkette wird direkt ausgedruckt mit dem Rest wie er ist. Das heißt: Wir müssen Register die Semikola in der Regex, auch wenn wir nicht wollen, dass sie ausgedruckt werden, sondern um sie durch Ignorieren ihrer übereinstimmenden Gruppe zu entfernen.

Normalerweise würde es ausreichen, nur die erfasste Gruppe auszudrucken, aber das funktioniert hier nicht. Um nur die Werte erfassen würde diese Ausgabe verursachen:

;;;;; 
<td>empty</td> 
<td>testvalue</td> 
<td>testvalue</td> 
<td>test"val"ue</td> 
<td>test value</td> 
<td>empty</td> 

Vielleicht brauchen wir die gesamte Zeichenfolge zunächst in einer anderen Gruppe zu erfassen, oder wir müssen die Semikolons in einer anderen Gruppe erfassen, um sie später im Druck wegzuwerfen heraus? ...

+1

ok, ich werde meine Frage aktualisieren, das Problem durch @ Stavr00 beschrieben zu ergreifen, mehrere Inline-Quotes berücksichtigen. – nilsun

+0

Sry Ich musste die favorisierte Antwortflagge aus Saleems Antwort wieder entfernen, da es immer noch nicht die beste Lösung zu sein scheint. Danke für alle Bemühungen bis hier, aber es gibt Anzeichen dafür, dass der kürzere Ansatz weniger Ressourcen benötigt, da er weniger Schritte benötigt, auch wenn er noch nicht perfekt ist. Um ein Ersatzmuster zu erzeugen, müssen wir die Semikolons entfernen. Also brauchen wir 2 ((Capture) Gruppen), eine für den extrahierten Wert $ 1 und die andere 2 (;) $ 2 für den Müll. – nilsun

Antwort

2

Sie diese viel einfacher Regex verwenden können mit einem Lookbehind mit inkludierten Semikolons in einer 3. Fanggruppe:

$str = ';testvalue;"testvalue";"test "val"ue";test value;'; 
preg_match_all('/(?<=;|^)("?)([^;]*)\1(;|$)/', $str, $matches); 

print_r($matches[2]); 

(?<=;|^) ist eine positive Lookbehind um sicherzustellen, dass wir [^;]* erst nach Zeilenstart oder ein ; sind passend.

Ausgang:

Array 
(
    [0] => 
    [1] => testvalue 
    [2] => testvalue 
    [3] => test "val"ue 
    [4] => test value 
    [5] => 
) 

RegEx Demo

und die erforderliche HTML zu erhalten:

echo "<td>" . implode("</td>\n<td>", $matches[2]) . "</td>\n"; 

<td></td> 
<td>testvalue</td> 
<td>testvalue</td> 
<td>test "val"ue</td> 
<td>test value</td> 
<td></td> 
+1

Vielen Dank für Ihre Antwort und Mühe! Dies ist ein großartiger und kurzer Ansatz, bei dem weniger Prozessschritte erforderlich sind. Ich habe Ihre Regex101 aktualisiert, um Capture-Gruppen für die extrahierten Spaltenwerte mit() hier zu erstellen https://regex101.com/r/wY5zJ9/2 - Würde es Ihnen etwas ausmachen, die Funktion von "Inline" q "uotes" wie aktualisiert in hinzuzufügen die OP-Frage? Dann möchte ich lieber deine Antwort bevorzugen. Vielen Dank! – nilsun

+0

Wow, du bist großartig. Danke für Ihre schnelle Antwort. Fast da :-) * blendet * sry, sieh dir die 4. Version hier an: https://regex101.com/r/wY5zJ9/4 -> Es zeigt das Problem mit mehreren Inline-Anführungszeichen immer noch da. Wir müssen auch noch (;) in einer 2. Spielgruppe fangen, um sie im Ersatzgebäude wegzuwerfen, ansonsten werden sie nicht entfernt. Sehen Sie sich die aktualisierte Frage an. Ich danke dir sehr. – nilsun

+0

Lassen Sie uns [diese Diskussion im Chat fortsetzen] (http://chat.stackoverflow.com/rooms/108557/discussion-between-anubhava-and-nilsun). – anubhava

2

Versuchen folgende PCRE regex:

\"(?:.*?)\"(?=;|$)|(?<=(?:;))(?:.*?)(?=;|$)|^(?:[^;]*?)(?=;) 

Von Probe String ;testvalue;"testvalue";"test value";test value; Regex erfassen:

Match 1:    
Match 2: testvalue 
Match 3: "testvalue" 
Match 4: "test value" 
Match 5: test value 
Match 6:    

Siehe Demo auf https://regex101.com/r/sU2jK5/2

+1

genial! Danke. Ist es in Ordnung, dass ich alles einfüge() um die jeweiligen Capture-Gruppen zu erstellen ;-)? Dann wäre es perfekt! Vielen Dank für Ihre schnelle Antwort. – nilsun

+1

Inline-Anführungszeichen funktionieren nicht richtig: 'test '" A "" Wert "sollte als" Test "analysiert werden A" Wert " – Stavr00

+0

Dies scheint so kompliziert und ineffizient zu sein. – anubhava