(в PHP 5.3.0 появилась функция [man]str_getcsv[/man] только речь о регулярках)
<?php
error_reporting(-1);
$line = '12,"153"",2",3,4,23,6';
$csv_regex = '{
\G(?:^|,)
(?:
# Поле в кавычках…
" # открывающая кавычка
( [^"]*+ (?: "" [^"]*+ )*+ )
" # закрывающая кавычка
| # …или…
# …произвольный текст, кроме кавычек и запятых…
( [^",]*+ )
)
}x';
header('Content-type: text/plain');
/* Применить регулярное выражение, заполнить $all_matches всеми типами данных
*/
preg_match_all($csv_regex, $line, $all_matches);
/* В $Result будут храниться поля, которые мы извлечем из $all_matches */
$Result = array ();
/* Обойти все успешные совпадения… */
for ($i = 0; $i < count($all_matches[0]); $i++)
{
/* Если это совпадение со второй парой сохраняющих скобок - использовать
* значение как есть */
if (strlen($all_matches[2][$i]) > 0)
array_push($Result, $all_matches[2][$i]);
else
{
/* Если это значение в кавычках, предварительно заменить
* последовательности из двух кавычек одной кавычкой */
array_push($Result, preg_replace('/""/', '"', $all_matches[1][$i]));
}
}
/* Теперь массив $Result заполнен и готов к дальнейшему использованию */
var_export($Result);
[/php]
выведет
[code]
array (
0 => '12',
1 => '153",2',
2 => '3',
3 => '4',
4 => '23',
5 => '6',
)
[/code]
Теперь сделаем безобидное, вроде бы, изменение: добавим пробелы.
[php]
$line = ' 12 , "153"" , 2" , 3 , 4, 23, 6 ';
[/php]
Логика нам подсказывает, что строка соответствует тем же самым данным. А наша регулярка облажалась:
[code]
array (
0 => ' 12 ',
1 => ' ',
)
[/code]
Методом тыка я нашел такой способ оживления. Первую фразу резулярки сделаем такой:
[code]
\G(?:^|\s*?,\s*?)
[/code]
вместо \s*? можно написать \s*+
результат:
[code]
array (
0 => ' 12 ',
1 => '153" , 2',
2 => '3 ',
3 => '4',
4 => '23',
5 => '6 ',
)
[/code]
Неплохо, только у под-строк, не заключённых в кавычки, появляются лишние концевые пробелы. В принципе это лечится пост-обработкой trim(), но неприятный осадочек есть.
Профи, подскажите новичку [b]лучшую[/b] регулярку для этих же целей.