2017-09-02 118 views
2

我想将基于文本的记帐文件转换为使用php的数组。每个验证线的结构如下:在php中迭代文本文件,多行作为一个迭代或子迭代也许

#VER A 14 20160715 "mats" 20161016 
{ 
#TRANS 1930 {} -3000.00 20160715 "mats" 
#TRANS 2893 {} 3000.00 20160715 "mats" 
} 
#VER A 15 20160719 "Mats" 20161016 
{ 
#TRANS 1930 {} -20000.00 20160719 "Mats" 
#TRANS 2893 {} 20000.00 20160719 "Mats" 
} 

所以我wan't遍历每行开始#VER然后subiterate开始与花括号之间#TRANS的线{}。在subiterate部分有问题。我的目标是一个数组,如下面的(希望没有错误...)

Array 
(
[#VER] => Array 
    (
     [A14] => Array 
      (
       [verdatum] => 20160714 
       [vertext] => mats 
       [trans] => Array 
        (
         [0] => Array 
          (
           [transaccount] => 1930 
           [transamount] => -3000.00 
           [transdate] => 20160715 
           [transtext] => mats 
          ) 
         [1] => Array 
          (
           [transaccount] => 2893 
           [transamount] => 3000.00 
           [transdate] => 20160715 
           [transtext] => mats 
          ) 

        ) 
      ) 
     [A15] => Array 
      (
       [verdatum] => 20160719 
       [vertext] => Mats 
       [trans] => Array 
        (
         [0] => Array 
          (
           [transaccount] => 1930 
           [transamount] => -20000.00 
           [transdate] => 20160719 
           [transtext] => Mats 
          ) 
         [1] => Array 
          (
           [transaccount] => 2893 
           [transamount] => 20000.00 
           [transdate] => 20160719 
           [transtext] => Mats 
          ) 

        ) 
      ) 
    ) 

) 

到目前为止的代码:

foreach($contentsarray as $line_value) 
{ 

    if (substr($line_value,0,4)=="#VER") { 
     list($ver, $serie, $vernr, $verdatum, $vertext, $verregdatum, $versign) = str_getcsv($line_value, ' '); 
     $verif[$ver][$serie.$vernr]['verdatum']= $verdatum; 
     $verif[$ver][$serie.$vernr]['vertext']= $vertext; 

    WHAT TO DO HERE? 

    } 

} 

任何指导大加赞赏。

+0

有很多方法可以做到这一点,但您必须从决定最终结果是什么开始。我们可以在你的代码中看到一些暗示,但这还远远没有完成。然后,您可以通过跟踪您所处的状态逐行解析它,但也可以使用行指针并使用代码的结构来保存状态。我想你打算做后者。 –

+0

请提供具体信息,输入,所需输出和当前输出。 –

+0

非常感谢迄今。上面添加了所需的输出 –

回答

1

我会去的正则表达式:

$fileContent = file_get_contents($filePath); 
if(preg_match_all('/^#VER(.*)\n{\n((^#TRANS.*\n)+)}/m', $fileContent, $matches)){ 
    foreach($matches[0] as $i=>$match){ 
     echo 'VER : '.$matches[1][$i].PHP_EOL; 
     echo 'TRANSes: '.$matches[2][$i].PHP_EOL; 
    } 
} 

UPDATE为所需的输出:

$fileContent = file_get_contents($filePath); 
if(preg_match_all('/^#VER(.*)\n{\n((^#TRANS.*\n)+)}/m', $fileContent, $matches)){ 
    foreach($matches[0] as $i=>$match){ 
     echo 'VER:'.$matches[1][$i].PHP_EOL; 
     if(preg_match_all('/^#TRANS (\d+) {} (-?\d+\.\d+) (\d{8}) "(.*)"/m', $matches[2][$i], $matches2)){ 
     foreach($matches2[0] as $j=>$match2){ 
      $trans = array('account' => $matches2[1][$j] 
          , 'amount' => $matches2[2][$j] 
          , 'date' => $matches2[3][$j] 
          , 'text' => $matches2[4][$j] 
         ); 
      print_r($trans); 
     } 
     } 
    } 
} 
+0

嗨萨尔。看起来很有趣。请参阅上面的答案,在那里我尝试了一些跟进问题的解决方案。 –

+0

非常好的解决方案,非常感谢!然而,看到我的新答案,我描述了一个小问题。 –

0

关于SAL的解决方案。看起来很有趣。试图建立它,但得到一个奇怪的输出。此代码:

if(preg_match_all('/^#VER(.*)\n{\n((^#TRANS.*\n)+)}/m', $fileContent,  $matches)){ 
     foreach($matches[0] as $i=>$match){ 
      echo 'VER : '.$matches[1][$i].PHP_EOL; echo "</br>"; 
      foreach($matches[2] as $x=>$match2){ 
      echo 'TRANS: '.$matches[2][$x].PHP_EOL; echo "</br>"; 
      } 
     } 
    } 

生成:

VER : A 14 20160715 "mats" 20161016 
TRANS: #TRANS 1930 {} -3000.00 20160715 "mats" #TRANS 2893 {} 3000.00 20160715 "mats" 
TRANS: #TRANS 1930 {} -20000.00 20160719 "Mats" #TRANS 2893 {} 20000.00 20160719 "Mats" 

VER : A 15 20160719 "Mats" 20161016 
TRANS: #TRANS 1930 {} -3000.00 20160715 "mats" #TRANS 2893 {} 3000.00 20160715 "mats" 
TRANS: #TRANS 1930 {} -20000.00 20160719 "Mats" #TRANS 2893 {} 20000.00 20160719 "Mats" 

希望得到如下:

VER : A 14 20160715 "mats" 20161016 
TRANS: #TRANS 1930 {} -3000.00 20160715 "mats" 
TRANS: #TRANS 2893 {} 3000.00 20160715 "mats" 
VER : A 15 20160719 "Mats" 20161016 
TRANS: #TRANS 1930 {} -20000.00 20160719 "Mats" 
TRANS: #TRANS 2893 {} 20000.00 20160719 "Mats" 
+0

你可以爆炸和substring第二组,但是,与另一个正则表达式会很容易。看到我更新的答案。 – Sal

0

SAL的解决方案似乎给人一种可行的解决方案。将代码更改为以下来构建我所需的数组。一个小问题是,当$ fileContent是存储在脚本中的字符串时,下面的工作正常,但是当更改为上传的文件时,代码不会输出数组。有关这可能是由于什么的想法?谷歌搜索,也许尾随空白停止代码?

$fileContent = iconv('CP437','UTF-8', file_get_contents($_FILES['userfile']['tmp_name'])); 
    if(preg_match_all('/^#VER(.*)\n{\n((^#TRANS.*\n)+)}/m', $fileContent, $matches)){ 
     foreach($matches[0] as $i=>$match){ 
      list($ver, $serie, $vernr, $verdatum, $vertext, $verregdatum, $versign) = str_getcsv($matches[1][$i].PHP_EOL, ' '); 
      $verif[$ver][$serie.$vernr]['verdatum']= $verdatum; 
      $verif[$ver][$serie.$vernr]['vertext']= $vertext; 

      if(preg_match_all('/^#TRANS (\d+) {} (-?\d+\.\d+) (\d{8}) "(.*)"/m', $matches[2][$i], $matches2)){ 
      foreach($matches2[0] as $j=>$match2){ 
       $verif[$ver][$serie.$vernr]['trans'][$j] = array('account' => $matches2[1][$j] 
           , 'amount' => $matches2[2][$j] 
           , 'date' => $matches2[3][$j] 
           , 'text' => $matches2[4][$j] 
          ); 
      } 
      } 
     } 
    print "<pre>"; 
    print_r($verif); 
    print "</pre>"; 


    }