【问题标题】:Merge 2 text files based on first column using php使用php根据第一列合并2个文本文件
【发布时间】:2016-04-13 14:48:53
【问题描述】:

我有 2 个包含多行的日志文件,例如

第一:

1|2016-04-13|...
3|2016-03-13|...

秒:

2|POST|accept: txt|...
3|POST|accept: txt|...

预期结果:

3|2016-03-13|...|POST|accept: txt|...

所以我需要使用 PHP 脚本根据第一列 (ID) 将所有数据合并到一个文件中。
注意:行数可以不同。只需要交叉点(顺序敏感)

【问题讨论】:

  • 是否必须在 PHP 中?如果你在 linux 系统上,“join”命令会做你想做的事;加入-t'|'文件1.txt 文件2.txt
  • 我需要 php 脚本,结果的顺序不应该改变

标签: php shell file concat


【解决方案1】:

打开两个日志文件。

您可以使用 fopen 和 fgets(在 foreach/while 循环中)将行放入数组

或使用 file_get_contents 将文件分解为 \n(在 Win 上为 \r\n)

现在您应该有两个数组,其中包含两个日志文件的行。 然后你这样做:

 $log1Lines = array("3|...|...", "4|...|...");
 $log2Lines = array("2|...|...", "3|...|...");

 $merged = array();

foreach($log1Lines as $row1){
     $id1 = explode("|", $row1)[0];
     foreach($log2Lines as $row2){
          $exploded = explode("|", $row2);
          $id2 = array_shift($exploded);
          if($id1 == $id2){
                $merged[$id1] = $row1 . "|" . implode("|", $exploded);
          }
     }
 }
 print_r($merged);

理论上它应该在没有循环的情况下是可行的(通过array_intersect比较两个数组之间的解析索引),但我现在没有解决方案。

希望对你有所帮助。

【讨论】:

    【解决方案2】:

    我最近需要写一些非常相似的东西,所以我根据你的格式对其进行了一些更新。如有必要,这将支持 2 个以上的文件,并允许更改分隔符。

    <?php
    class Merger
    {
        protected $separator = '|';
        protected $data = [];
        protected $initialised = false;
    
        public function mergeFile($filename)
        {
            $file = new SplFileObject($filename);
            $fileKeys = [];
    
            // Read the information out of the current file
            while (!$file->eof()) {
                $line = $file->fgets();
                $parts = explode($this->separator, trim($line));
                $id = array_shift($parts);
                $fileKeys[] = $id;
    
                $fileData[$id] = $parts;
            }
    
            // First pass: add everything
            if (!$this->initialised)
            {
                $this->data = $fileData;
            }
    
            // Subsequent passes, only add things that have already been seen, then
            // clear out anything that wasn't in the current file
            else
            {
                foreach ($fileData as $id => $data)
                {
                    if ($this->data[$id])
                    {
                        $this->data[$id] = array_merge($this->data[$id], $data);
                    }
                }
    
                $this->data = array_filter($this->data, function ($e) use ($fileKeys) {
                    return in_array($e, $fileKeys);
                }, ARRAY_FILTER_USE_KEY);
            }
    
            $this->initialised = true;
        }
    
        public function output($filename)
        {
            foreach ($this->data as $id => $data)
            {
                $output .= $id . $this->separator . implode($this->separator, $data) . PHP_EOL;
            }
    
            file_put_contents($filename, $output);
        }
    }
    
    $merger = new Merger;
    $merger->mergeFile('1.txt');
    $merger->mergeFile('2.txt');
    
    echo $merger->output('output.txt');
    

    【讨论】:

      【解决方案3】:

      我的解决办法是:

      <?php 
          exec ("awk -F'|' -vOFS='|' '(NR==FNR){a[$1]=$0; next}{if(a[$1]){print $2,a[$1]}}' first.log second.log > result.log");
      ?>
      

      我使用execphp函数执行shell脚本

      awk -F'|' -vOFS='|' '(NR==FNR){a[$1]=$0; next}{if(a[$1]){print $2,a[$1]}}' first.log second.log > result.log
      

      这里-F'|' 指定'|'符号作为分隔符,first.logsecond.log 是我要合并的文件。

      【讨论】:

        猜你喜欢
        • 2019-12-29
        • 2011-05-03
        • 2019-11-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-06-20
        • 2015-02-21
        • 1970-01-01
        相关资源
        最近更新 更多