2017-04-15 31 views
1

好吧,你好社區。我在PHP中使用CSV解碼器工作(是的,我知道已經有一個,但作爲我的挑戰,因爲我在空閒時間學習)。現在的問題是:行被拆分爲PHP_EOL用分號分割不被引號包圍

在這一行:

foreach(explode($sep, $str) as $line) { 

其中是其將向上行和STR我想解碼字符串變量。

但是,如果我想用分號分隔列,那麼可能會出現分號只包含一列的情況。當我研究這個問題是由報價跡象像這樣整列周圍的解決:

輸入:

"0;0";1;2;3;4 

預期輸出:

0; 0 | 1 | 2 | 3 | 4

我已經想到了超前/後視。但是,因爲我以前沒有使用它,也許這可能是一個很好的做法,我不知道如何將它包含在正則表達式中。我的解碼函數返回一個二維陣列(如表...),我想加入行這樣的陣列(是的,正則表達式是f ***編向上...)的:

$res[] = preg_split("/(?<!\")". preg_quote($delim). "(?!\")/", $line); 

,最後我全碼:

function csv_decode($str, $delim = ";", $sep = PHP_EOL) { 
    if($delim == "\"") $delim = ";"; 
    $res = []; 

    foreach(explode($sep, $str) as $line) { 
     $res[] = preg_split("/(?<!\")". preg_quote($delim). "(?!\")/", $line); 
    } 

    return $res; 
} 

提前感謝!

回答

1

您可以使用此功能str_getcsv在此您也可以指定一個自定義分隔符(;)。

Try this code snippet

<?php 

$string='"0;0";1;2;3;4'; 
print_r(str_getcsv($string,";")); 

輸出:

Array 
(
    [0] => 0;0 
    [1] => 1 
    [2] => 2 
    [3] => 3 
    [4] => 4 
) 
+0

在想着同樣的方法,以避免正則表達式,也是一個數組的步行路程將是很好,解析'0;和0'沒有它作爲字符串,但作爲一個數組。 – Gntem

+0

@ Mr.Phoenix我還沒有使用過正則表達式,這裏我使用了一個'PHP'的內置函數。 –

+1

它適用於$ string。但是當從雙引號改爲單引號時:$ string =「'0; 0'; 1; 2; 3; 4」;它失敗了。 –

2

這有點違反直覺的,但正則表達式來分割字符串的最簡單的方法往往是在地方preg_split使用preg_match_all

preg_match_all('~("[^"]*"|[^;"]*)(?:;|$)~A', $line, $m); 
$res[] = $m[1]; 

A修飾符確保鄰接o f從字符串開始的連續匹配。

如果你不想被包括在結果的報價,則可以使用branch reset feature(?|..(..)..|..(..)..)

preg_match_all('~(?|"([^"]*)"|([^;"]*))(?:;|$)~A', $line, $m); 

其他解決辦法,但這個時候preg_split:包括你想要的部分避免分隔符之前和使用\K功能從整場比賽丟棄它:

$res[] = preg_split('~(?:"[^"]*")?\K;~', $line); 
+0

這幫了我一點tbh。也許對於一個(讓我說)高級初學者(因爲我不是0技能爲主,但我明明只知道像捕獲組的基礎知識,信件類等這麼先進的初學者,沒有中間)我希望更多的解釋,因爲許多這樣的功能對我來說是全新的。 – iBinary

+0

讓我試試吧: 第一個正則表達式:第一個捕獲組是一個引號符號後跟許多沒有引號登錄字符或多個無-分號字符和非報價登錄字符。然後一個包含分號或美元符號的非捕獲(這意味着字符串的結尾?我很困惑......)? – iBinary

+0

第二個:所提到的分支復位該IDK的組...捕獲組1包括許多沒有引號登錄字符,這組由兩個引號包圍的跡象。第1組也可以包含許多非分號字符或無引號的符號。未捕獲的組包括分號或美元符號。 – iBinary

0

分裂是不是去od csv類型行的選擇。
你可以使用舊的嘗試和真正的\G錨與全球尋找類型FUNC。

Practical

正則表達式:'~\G(?:(?:^|;)\s*)(?|"([^"]*)"|([^;]*?))(?:\s*(?:(?=;)|$))~'

信息:

\G       # G anchor, start where last match left off 
(?:       # leading BOL or ; 
     (?:^| ;) 
     \s*       # optional whitespaces 
) 
(?|       # branch reset 
     " 
     ([^"]*)      # (1), double quoted string data 
     " 
    |        # or 
     ([^;]*?)     # (1), non-quoted field 
) 
(?:       # trailing optional whitespaces 
     \s* 
     (?: 
      (?= ;)      # lookahead for ; 
     | $        # or EOL 
    ) 
)