2012-01-17 2 views
0

Я пытаюсь вырвать строку из файла CSV без использования синтаксического анализатора, и все, что мне нужно сделать, это разбить строку на основе запятых, используя php , Само по себе это довольно легко, если на входе нет запятых, что не так. Я хочу игнорировать запятые, которые заключены в двойные кавычки.Regex: Matching ',' после нулевого или нечетного вхождения двойной кавычки

Полностью игнорируя последнее предложение, я решил изменить эту проблему ставит перед собой следующие:

Я хочу, чтобы разделить строку, основываясь на запятые, которые предшествуют без двойных кавычек или разбросанные пары двойных кавычек.

Пример:

text,"some,"chars,chars"more,""text", 
    *  x  *   x  * 

Где * результаты и х не является.

Является ли это невозможным регулярным выражением, а если нет, существует ли регулярное выражение, которое может обрабатывать этот вид ввода?

+3

Есть ли какая-либо конкретная причина, почему вы не хотите использовать str_getcsv() http://uk3.php.net/manual/en/function.str-getcsv.php? Кстати, строка вашего примера будет недействительной, так как «внутри» должно быть экранировано или у вас есть капли, такие как «некоторые», символы, которые неправильно указаны, когда они должны быть –

+0

. Я уверен, что это можно сделать, но это, вероятно, проще использовать что-то вроде 'fgetcsv()' для синтаксического анализа для вас. – Arjan

+0

Можно сделать. На самом деле у меня есть один, но он больше соответствует стандартным правилам CSV, а не варианту экранирования и значениям в смешанных кавычках/без кавычек. – mario

ответ

1

Я уверен, что это может быть написано гораздо лучше, но вот вариант, который работает для вашего случая:

preg_match_all('/ 
    \s* ((?: (?=.|(?<=,)$) [^",]* | "(?: ""|[^"]*)+")+) \s* (?:,|$) /xms', 
    $line, $matches 
) 
and print_r($matches[1]); 

Но это не чтит другие типичные правила CSV. Обычно я ожидал бы \", чтобы избежать двойных кавычек. И смешанные котируемые и некотируемые подстроки также очень нестандартны. И он не имеет какой-либо формы проверки, поэтому просто не будет пропустить ни одну последнюю цитату - независимо от того, правильно ли она спаривается.

Для тестовой строки:

 [0] => text 
     [1] => "some,"chars 
     [2] => chars"more,""text" 
     [3] => 
1

Если файл CSV правильно (каждое поле либо начинается и заканчивается с «или не содержит», то можно разобрать строку с рекурсивной функцией, вот так:.

$csvString = 'zero,"o,ne",two,"thr,ee"'; 

function parseCsv($string, &$result) 
{ 
    $regex = '/^((".*")|([^"].*))(,(.*))?$/U'; 
    $matches = array(); 
    preg_match($regex, $string, $matches); 
    $result[] = $matches[1]; 
    if(isset($matches[5])) 
    { 
     parseCsv($matches[5], $result); 
    } 
} 

$result = array(); 
parseCsv($csvString, $result); 

var_dump($result); 

Обратите внимание, что это не было протестировано с кавычками строк, которые содержат (беглый) цитирует Также он держит кавычки строки в кавычках

результата. выше функция

array 
    0 => string 'zero' (length=4) 
    1 => string '"o,ne"' (length=6) 
    2 => string 'two' (length=3) 
    3 => string '"thr,ee"' (length=8) 
Смежные вопросы