【问题标题】:How to parse a fixed width text file in PHP? [duplicate]如何在 PHP 中解析固定宽度的文本文件? [复制]
【发布时间】:2012-10-19 17:42:31
【问题描述】:

我有大量数据,如下所示:

 PHHI   GFSX MOS GUIDANCE  10/19/2012  1200 UTC                       
 FHR  24  36| 48  60| 72  84| 96 108|120 132|144 156|168 180|192      
      SAT 20| SUN 21| MON 22| TUE 23| WED 24| THU 25| FRI 26|SAT CLIMO
 N/X  66  80| 68  82| 66  82| 66  81| 66  80| 67  82| 67  81| 67999999
 TMP  69  79| 71  81| 69  80| 69  80| 69  79| 69  80| 70  80| 70      
 DPT  63  64| 66  63| 64  64| 65  64| 65  66| 66  68| 68  65| 66      
 WND  11  10| 10  12| 11   9|  9   8|  8   8|  8   8|  8   7|  7      
 P12   8   9| 11   9| 21  14| 20  10| 18  20| 28  28| 46  15| 32999999
 P24      14|     19|     14|     23|     19|     36|     40|      999
 Q12   0   0|  0   0|  0   0|  0   0|  0   0|  1   1|       |         
 Q24       0|      0|      0|      0|      0|      1|       |         

 PHJH   GFSX MOS GUIDANCE  10/19/2012  1200 UTC                       
 FHR  24  36| 48  60| 72  84| 96 108|120 132|144 156|168 180|192      
      SAT 20| SUN 21| MON 22| TUE 23| WED 24| THU 25| FRI 26|SAT CLIMO
 N/X 999  84|999  84|999  84|999  85|999  84|999  84|999  84|999999999
 TMP 999  83|999  82|999  83|999  83|999  83|999  83|999  83|999      
 ........etc

我需要在 PHP 中对其进行处理,以便可以将其放入 MYSQL 数据库中。

在第一行,需要第一个单词(电台名称)和日期/时间。 根本不需要第二行和第三行。 | 字符无关紧要。 最后两列有问题:

192      
SAT CLIMO
 67999999
 70      
 66      
  7      
 32999999
      999

这些数字相互接触,但实际上它们是 2 个独立的变量。它应该看起来更像这样:

192      
SAT CLIMO
 67 999999
 70      
 66      
  7      
 32 999999
      999

关于如何解析这个的任何提示?是否有任何用于解析固定宽度数据的辅助功能?

【问题讨论】:

  • 固定宽度让解析变得超级容易,有什么问题?只是子串它。

标签: php parsing


【解决方案1】:

这是 O'Reilly PHP Cookbook 中回答的经典 PHP 问题。

Parsing Fixed-Width Delimited Data

substr 工作正常。不过,unpack 是我最喜欢的,因为它在底层使用了 C 函数,而且速度更快。

【讨论】:

    【解决方案2】:

    你可以试试

    $file = "log.txt";
    $list = $part = array();
    
    foreach ( file($file) as $line ) {
        $line = trim($line);
        if (strpos($line, "|") === false) {
            continue;
        }
        $line = explode("|", $line) and $line = end($line);
        $list[] = substr($line, 0, 3) . " " . substr($line, 3);
    }
    var_dump($list);
    

    输出

    array
      0 => string '192 ' (length=4)
      1 => string 'SAT  CLIMO' (length=10)
      2 => string ' 67 999999' (length=10)
      3 => string ' 70 ' (length=4)
      4 => string ' 66 ' (length=4)
      5 => string '  7 ' (length=4)
      6 => string ' 32 999999' (length=10)
      7 => string '       999' (length=10)
      8 => string ' ' (length=1)
      9 => string ' ' (length=1)
      10 => string '192 ' (length=4)
      11 => string 'SAT  CLIMO' (length=10)
      12 => string '999 999999' (length=10)
      13 => string '999 ' (length=4)
    

    【讨论】:

    • 这不是解析固定数据的解决方案。它在分隔符上拆分。把柱子弄脏了,它仍然可以工作。那不是合同。如上所述,为每列指定列开始和长度并使用 substr()。
    【解决方案3】:

    过去我使用 substr() 函数从特定字段获取数据:

    http://php.net/manual/en/function.substr.php

    例如:

    //Index:
    
    012345678
    
    192      
    SAT CLIMO
     67999999
     70      
     66      
      7      
     32999999
          999
    

    对于第一列,我会有类似的内容:

    while($line = fgets($file)){
    
        $column1 = substr($line, 0, 3);
        $column2 = substr($line, 3, 6);
    }
    
    // for the line 32999999, you get:
    // $column1 = 32
    // $column2 = 999999
    

    您可以将这些索引设为常量,并且必须先尝试使用它才能通过一些字符计数来使其正确,但这将解决数字一起运行的问题。

    【讨论】:

      【解决方案4】:

      我会在这里使用fscanf 函数。

      【讨论】:

        猜你喜欢
        • 2012-06-10
        • 1970-01-01
        • 2011-06-22
        • 2017-04-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-25
        相关资源
        最近更新 更多