2010-11-22 5 views
2

Ich suche nach einem regulären Ausdruck mit preg_match_all in PHP 5, die es mir erlauben würde, eine Zeichenfolge durch Kommas zu trennen, solange die Kommas nicht existieren in einfachen Anführungszeichen, die es ermöglichen, einzelne Anführungszeichen zu umgehen. Beispieldaten wäre:REGEX: Aufteilen durch Kommas, die nicht in einfache Anführungszeichen sind, die escaped Anführungszeichen erlaubt

(some_array, 'some, string goes here','another_string','this string may contain "double quotes" but, it can\'t split, on escaped single quotes', anonquotedstring, 83448545, 1210597346 + '000', 1241722133 + '000') 

Dies sollte eine Übereinstimmung erzeugen, die wie folgt aussieht:

(some_array 

'some, string goes here' 

'another_string' 

'this string may contain "double quotes" but, it can\'t split, on escaped single quotes' 

anonquotedstring 

83448545 

1210597346 + '000' 

1241722133 + '000') 

ich viele, viele reguläre Ausdrücke versucht haben ... Meine aktuelle sieht wie folgt aus, obwohl es doesn nicht 100% korrekt. (Es spaltet noch einige Kommas in einfache Anführungszeichen.)

"/'(.*?)(?<!(?<!\\\)\\\)'|[^,]+/" 
+1

* Dies kann * getan werden, aber es ist eher härter als die meisten Leute sich vorstellen; sieht aus, als würdest du jetzt ein Gefühl für die Schwierigkeit bekommen. Gibt es da wirklich keine Bibliotheksfunktion, die das in PHP erledigt? Es gibt in Perl. Wenn Sie bis dahin keine gute Antwort erhalten, kann ich versuchen, den Regex später für Sie zusammenzustellen. – tchrist

Antwort

7

Haben Sie str_getcsv versucht? Es tut genau das, was Sie ohne einen regulären Ausdruck brauchen.

$result = str_getcsv($str, ",", "'"); 

Sie können auch diese Methode in PHP-Versionen implementieren älter als 5.3, Abbildung auf fgetcsv mit diesem Ausschnitt aus a comment in der Dokumentation:

if (!function_exists('str_getcsv')) { 

    function str_getcsv($input, $delimiter = ',', $enclosure = '"', $escape = null, $eol = null) { 
     $temp = fopen("php://memory", "rw"); 
     fwrite($temp, $input); 
     fseek($temp, 0); 
     $r = fgetcsv($temp, 4096, $delimiter, $enclosure); 
     fclose($temp); 
     return $r; 
    } 

} 
+1

Diese Lösung hat funktioniert. str_getcsv war keine gültige Funktion, da ich PHP 5.3+ nicht benutze – JordanL

+0

Leider ist str_getcsv nicht konsistent über die Art, wie es Kommas in einfache Anführungszeichen behandelt: http://3v4l.org/Ubk1U – greggles

+1

@greggles: Mir ist das nicht bekannt von allen Interpretationen von CSV, die einfache Anführungszeichen als String-Enclosure zulassen. Es ist auch nicht in [RFC 4180] (http://tools.ietf.org/html/rfc4180), aber PHP lässt Sie das Gehäuse in einfache Anführungszeichen gemäß den Dokumenten setzen. –

2

In PHP 5.3 ab kann man sich diesen Schmerz sparen mit str_getcsv

$data=str_getcsv($input, ",", "'"); 

Ihr Beispiel zu nehmen ...

$input=<<<STR 
(some_array, 'some, string goes here','another_string','this string may contain "double quotes" but it can\'t split on escaped single quotes', anonquotedstring, 83448545, 1210597346 + '000', 1241722133 + '000') 
STR; 

$data=str_getcsv($input, ",", "'"); 
print_r($data); 

Ausgänge dieses

Array 
(
    [0] => (some_array 
    [1] => some, string goes here 
    [2] => another_string 
    [3] => this string may contain "double quotes" but it can\'t split on escaped single quotes 
    [4] => anonquotedstring 
    [5] => 83448545 
    [6] => 1210597346 + '000' 
    [7] => 1241722133 + '000') 
) 
+1

Christus .... Ich fühle mich dumm, lol ...Ich habe PHP seit acht Jahren programmiert und habe diese Funktion nie benutzt. – JordanL

0

Ich zweite die Verwendung eines CSV-Parser hier, das ist, was sie sind da.

Wenn Sie mit regex stecken, Sie

preg_match_all(
    '/\s*" # either match " (optional preceding whitespace), 
    (?:\\\\. # followed either by an escaped character 
    |  # or 
    [^"]  # any character except " 
    )*  # any number of times, 
    "\s*  # followed by " (and optional whitespace). 
    |   # Or: do the same thing for single-quoted strings. 
    \s*\'(?:\\\\.|[^\'])*\'\s* 
    |   # Or: 
    [^,]*  # match anything except commas (i.e. any remaining unquoted strings) 
    /x', 
    $subject, $result, PREG_PATTERN_ORDER); 
$result = $result[0]; 

verwenden könnte Aber, wie Sie sehen können, ist dies hässlich und schwer zu pflegen. Verwenden Sie das richtige Werkzeug für den Job.

2

Mit einigen Blick hinter können Sie etwas in der Nähe zu bekommen, was Sie wollen:

$test = "(some_array, 'some, string goes here','another_string','this string may contain \"double quotes\" but, it can\'t split, on escaped single quotes', anonquotedstring, 83448545, 1210597346 + '000', 1241722133 + '000')"; 
preg_match_all('` 
(?:[^,\']| 
    \'((?<=\\\\)\'|[^\'])*\')* 
`x', $test, $result); 
print_r($result); 

Gibt Ihnen dieses Ergebnis:

Array 
(
    [0] => Array 
     (
      [0] => (some_array 
      [1] => 
      [2] => 'some, string goes here' 
      [3] => 
      [4] => 'another_string' 
      [5] => 
      [6] => 'this string may contain "double quotes" but, it can\'t split, on escaped single quotes' 
      [7] => 
      [8] => anonquotedstring 
      [9] => 
      [10] => 83448545 
      [11] => 
      [12] => 1210597346 + '000' 
      [13] => 
      [14] => 1241722133 + '000') 
      [15] => 
     ) 

    [1] => Array 
     (
      [0] => 
      [1] => 
      [2] => e 
      [3] => 
      [4] => g 
      [5] => 
      [6] => s 
      [7] => 
      [8] => 
      [9] => 
      [10] => 
      [11] => 
      [12] => 0 
      [13] => 
      [14] => 0 
      [15] => 
     ) 

) 
+0

Was ist das zweite Array, das "e g s 0" hat? Ist das deine Absicht, einfach weggeworfen zu werden? – greggles

Verwandte Themen