首页 > 解决方案 > 将特定的 txt 文件解析为 csv 时避免排除相似的行

问题描述

我需要将纯文本文件解析csv 文件(也是纯文本格式)。所以我有一个在 PHP 版本 5.3.13 的服务器上运行的 php 脚本。而且没有办法升级。它工作得很好……

第一的。这是 php 脚本:(它是完整的工作脚本

<?php
// INPUT RAW FILE -- UTF8 !!!!
$data = trim(file_get_contents('inbox_file_utf8_clean.txt'));

$all_lines = preg_split("/\r?\n/", $data);
$date_id_line = array_shift($all_lines);
if(!preg_match('/^\d+\s\w+\s(?<time>\d+:\d+)\sId:\s(?<id>\d+).*/', $date_id_line, $matches)) {
  trigger_error('Failed to match ID and timestamp', E_USER_ERROR);
}
$output_data = array(
  'info' => array(
    'id' => $matches['id'],
    'time' => $matches['time']
  ),
  'data' => array()
);

$all_text_headers = array_values(preg_grep('/^\s*\(/', $all_lines));

// The first "Text header" is a parent.
// Count the number of leading whitespaces to determine other parents
preg_match('/^\x20*/', $all_text_headers[0], $leading_space_matches);
$leading_spaces = $leading_space_matches[0];
$num_leading_spaces = strlen($leading_spaces);
$parent_lead = str_repeat(' ', $num_leading_spaces) . '(';
$parent = NULL;
foreach($all_text_headers as $index => $header_line) {
  list($lead, $item_value) = explode(') ', $header_line);
  list($topic, $topic_count) = array_map('trim',
    preg_split('/\s{2,}/', $item_value, -1, PREG_SPLIT_NO_EMPTY)
  );

  $topic_count = preg_replace('/\D/', '', $topic_count);

  if($is_parent = ($parent === NULL || strpos($lead, $parent_lead) === 0)) {
    $parent = $topic;
  }

  if($is_parent) {
    $output_data['data'][$parent] = array(
      'count' => $topic_count,
      'values' => array(),
    );
  } else {
    $output_data['data'][$parent]['values'][] = array(
      'topic' => $topic,
      'count' => $topic_count
    );
  }
}

$csv_delimiter = ';';
//output file -- result file -- CSV -- 
$handle = fopen('csv.txt', 'wb');

fputcsv($handle, array_values($output_data['info']), $csv_delimiter);

foreach($output_data['data'] as $parent_topic => $data) {
  $child_data = array();
  if($data['values']) {
    foreach($data['values'] as $arr) {
      $child_data[] = sprintf('%s x%d', $arr['topic'], $arr['count']);
    }
  }
  fputcsv($handle, array(
    $parent_topic,
    $data['count'],
    implode(', ', $child_data)
  ), $csv_delimiter);
}

fclose($handle);

echo "it's kinda done :-)";

$order_num = $matches['id'];

sleep(4);
?>

我需要解析的文件如下所示:(该示例是我必须解析的真正纯文本文件。它只是一个 utf8 编码的纯文本文件。它是真正的“输入”文本文件。

18 jun 15:28 Id: 42 #1 Random Text                                     
(Text header 1) Apple                    15
   (Text header 1) Really long line           
   here is the rest of the             
   long line that does'n get parsed
(Text header 1) Milk          2
(Text header 1) Ice cream                   4
(Text header 1) Ice cream                   4
(Text header 1) Pencil            1
(Text header 1) Box                    1
   (Text header 1) Cardboard                 x1
   (Text header 1) White                 x1
   (Text header 1) Cube              x1
(Text header 1) Phone     1
   (Text header 1) Specific text                x1
   (Text header 1) Symbian                x1

格式描述是:只是一个纯文本文件。第一行是标题。所有其余的行(除了以空格开头的行)都是“索引”行。所有以前导空格开头的行都是“子”行

我得到了输出结果 csv 文件:(那个例子是一个真正的纯文本输出。

42;15:28
Apple;15;Really long line;
Milk;2;
"Ice cream";4;
Pencil;1;
Box;1;"Cardboard x1, White x1, Cube x1";
Phone;1;"Specific text x1, Symbian x1";

我有一个问题

如果输入文件包含两条相似的行,则输出的 csv 文件包含这两行之一。我需要他们两个。

所以在示例输入文件中,我有两个“冰淇淋”。但输出只包含一个“冰淇淋”。我怎样才能让它们都被解析?

请帮忙...

标签: phpcsvparsing

解决方案


推荐阅读