Регулярное выражение: сопоставление ',' после нуля или нечетного вхождения двойной кавычки
Я пытаюсь отделить строку из файла CSV без использования анализатора, и все, что мне нужно сделать, это разделить строку на основе запятых с помощью php. Само по себе это довольно просто, если у вас нет запятых на входе, что не так. Я хочу игнорировать запятые, которые заключены в двойные кавычки.
Полностью игнорируя последнее предложение, я решил изменить саму проблему на следующую:
Я хочу разбить строку на основе запятых, которым не предшествуют двойные кавычки или разбросанные пары двойных кавычек.
Пример:
text,"some,"chars,chars"more,""text",
* x * x *
Где * - совпадения, а x - нет.
Это за пределами способности регулярного выражения, и если нет, есть ли регулярное выражение, которое может обрабатывать этот тип ввода?
2 ответа
Я уверен, что это может быть написано намного лучше, но вот вариант, который работает для вашего случая:
preg_match_all('/
\s* ((?: (?=.|(?<=,)$) [^",]* | "(?: ""|[^"]* )+" )+) \s* (?:,|$) /xms',
$line, $matches
)
and print_r($matches[1]);
Но это не соблюдает другие типичные правила CSV. Я бы обычно ожидал \"
чтобы избежать двойных кавычек внутри. И смешанные кавычки и не заключенные в кавычки подстроки также очень нестандартны. И в ней отсутствует какая-либо форма проверки, поэтому она просто пропустит любую последнюю цитату - что угодно, если не правильно спарено.
Для вашей тестовой строки:
[0] => text
[1] => "some,"chars
[2] => chars"more,""text"
[3] =>
Если ваш 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)