Как можно проанализировать данные Excel CSV, которые содержат разрывы строки в данных?

Я пытаюсь проанализировать ряд данных CSV с помощью PHP, но имея главную проблему. Одно из полей является длинным полем описания, которое самим содержит разрывы строки в корпусах.

Моя основная проблема пишет часть кода, который может разделить данные линию за линией, но также и распознать, когда разрывы строки в данных не должны использоваться. Разрывов строки в этом поле правильно не оставляют, делая их трудно для различения от законных разрывов строки.

Я попытался придумать регулярное выражение, которое может правильно обработать его, но не имело никакой удачи до сих пор. Какие-либо идеи?

Формат CSV:

"####","text data here", "text data \n with linebreaks \n here"\n
"####","more text data", "more data \n with \n linebreaks \n here"\n
6
задан omgitsfletch 3 February 2014 в 05:06
поделиться

3 ответа

По словам Алеске, комментатора в документации для функции PHP fgetcsv :

Обработка файлов CSV в PHP нестандартна и противоречит RFC4180, таким образом, fgetcsv ( ) не может правильно работать с файлами [которые содержат разрывы строк] ...

И он предложил следующую функцию, чтобы обойти это ограничение:

function csvstring_to_array(&$string, $CSV_SEPARATOR = ';', $CSV_ENCLOSURE = '"', $CSV_LINEBREAK = "\n") { 
  $o = array(); 

  $cnt = strlen($string); 
  $esc = false; 
  $escesc = false; 
  $num = 0; 
  $i = 0; 
  while ($i < $cnt) { 
$s = $string[$i]; 

if ($s == $CSV_LINEBREAK) { 
  if ($esc) { 
    $o[$num] .= $s; 
  } else { 
    $i++; 
    break; 
  } 
} elseif ($s == $CSV_SEPARATOR) { 
  if ($esc) { 
    $o[$num] .= $s; 
  } else { 
    $num++; 
    $esc = false; 
    $escesc = false; 
  } 
} elseif ($s == $CSV_ENCLOSURE) { 
  if ($escesc) { 
    $o[$num] .= $CSV_ENCLOSURE; 
    $escesc = false; 
  } 

  if ($esc) { 
    $esc = false; 
    $escesc = true; 
  } else { 
    $esc = true; 
    $escesc = false; 
  } 
} else { 
  if ($escesc) { 
    $o[$num] .= $CSV_ENCLOSURE; 
    $escesc = false; 
  } 

  $o[$num] .= $s; 
} 

$i++; 
  } 

//  $string = substr($string, $i); 

  return $o; 
} 

Похоже, это поможет.

10
ответ дан 8 December 2019 в 17:18
поделиться

В итоге я смог изменить регулярное выражение с помощью определенных специальных флагов, чтобы они работали для моих нужд. Я использовал следующий вызов функции:

preg_match_all('/"\d+",".*",".*"\n/sU', $csv_data, $matches);

Кажется, это работает по нескольким причинам:

1) Флаг 's' указывает редактору перехватывать новые строки под точкой, что обычно не так. Прискорбный побочный эффект этого заключается в том, что допустимые символы новой строки также перехватываются точкой, что теоретически может привести весь CSV к одному результату, поэтому

2) я добавил флаг U. Это говорит о том, что точка по умолчанию не является жадной, и поэтому в настоящее время она соответствует только одной строке за кусок.

0
ответ дан 8 December 2019 в 17:18
поделиться

Для синтаксического анализа csv можно использовать fgetcsv или strgetcsv . Посмотрите примеры в документации php.

-2
ответ дан 8 December 2019 в 17:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: