2017-09-02 119 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>"; 


    }