【问题标题】:Unix:merge multiple CSV files with same header by keeping the header of the first fileUnix:通过保留第一个文件的标题来合并具有相同标题的多个 CSV 文件
【发布时间】:2013-05-29 05:46:16
【问题描述】:

我必须合并多个具有相同标题的 CSV 文件。 我必须保留第一个文件的标题并删除所有其他文件的标题并将它们合并并创建一个主文件。

文件 1:

Id,city,name ,location
1,NA,JACK,CA

文件 2:

ID,city,name,location
2,NY,JERRY,NY

输出:

Id,city,name,location
1,NA,JACK,CA
2,NY,JERRY,NY

目前我正在使用此代码:

ls *.csv | xargs -n 1 tail -n+2 > master.csv

此代码将完美地合并文件,但由于我需要第一个文件的标题,这不会给我标题。

我该怎么办?

【问题讨论】:

  • 这是一个追加操作,不是合并。也许有人可以编辑问题标题以更好地代表内容。

标签: unix csv


【解决方案1】:
awk 'FNR==1 && NR!=1{next;}{print}' *.csv

在 solaris unix 上测试:

> cat file1.csv
Id,city,name ,location
1,NA,JACK,CA
>
> cat file2.csv
ID,city,name,location
2,NY,JERRY,NY
>
> nawk 'FNR==1 && NR!=1{next;}{print}' *.csv
Id,city,name ,location
1,NA,JACK,CA
2,NY,JERRY,NY
> 

kevin-d给出的解释:

FNR 是当前文件中到目前为止读取的行数(记录)。 NR 是整体读取的行数。所以条件 'FNR==1 && NR!=1{next;}' 说,“如果它是 当前文件,并且至少已经读取了 1 行。”这有 在跳过第一个文件的同时打印第一个文件的 CSV 标题的效果 其余的。

Link的区别

【讨论】:

  • 解释:FNR 是当前文件中到目前为止读取的行数(记录)。 NR 是整体读取的行数。所以条件 'FNR==1 && NR!=1{next;}' 说,“如果它是当前文件的第一行,则跳过这一行,并且至少有 1 行已被整体读取。”这具有打印第一个文件的 CSV 标题同时在其余部分跳过它的效果。
  • 对于像我这样的菜鸟...我在末尾添加了 > master.csv 以创建包含所有数据的新文件,而不是运行 CLI
【解决方案2】:

如果 Perl 是一个选项:

perl -ne 'print if $. > 1 or ! $h; $h=1; close ARGV if eof' *.csv > master.csv

$. 是行号。
它不会在文件之间自动重置,因此需要close ARGV if eof
$h 记录是否已打印标题。

【讨论】:

    【解决方案3】:
    <?php
    ini_set('auto_detect_line_endings', true);
    $dir = "include/*.csv";
    $returnVal = array();
    foreach (glob($dir) as $file) {
        $header = null;
        $file = fopen($file, 'r') or die('Unable to open file!');
        while(($row = fgetcsv($file)) !== false){
            if($header === null){
                $header = $row;
                continue;
            }
            $newRow = array();
            for($i = 0; $i<count($row); $i++){
    
                $newRow[] = $row[$i];   
            }
            if($newRow[0] == null)
            break;
            else
            $returnVal[] = $newRow;
        }
        fclose($file);
    }
    //var_dump($returnVal);
    $output = fopen("file.csv",'w') or die("Can't open output");
    fputcsv($output, array('Date','close','open'));
    foreach($returnVal as $product) {
        fputcsv($output, $product);
    }
    

    fclose($output) 或 die("无法关闭 php://output"); ?>

    【讨论】:

    • 粘贴代码是不够的。告诉我们一些关于它的事情。
    【解决方案4】:

    作为对使用该线程已接受解决方案的每个人的旁注(也像我一样:)) - 请注意,如果标题包含新行,则此代码将失败,即类似

    column1,"column\nwith\new line",column2
    value1,value2,value3
    ...
    

    在这种情况下,只有column1,"column 部分将被视为标题,而标题的其余部分将被视为正常行(这将完全破坏您的最终 CSV)。如果您有一个带有新行的标题,我能想到的唯一解决方案是使用能够正确读取标题的“成熟”csv阅读器库。

    但是尽管有这个小问题,上面的那行让我免于头疼。 :D

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-15
      • 1970-01-01
      相关资源
      最近更新 更多