我必须合并多个具有相同标题的 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
此代码将完美合并文件,但由于我需要第一个文件的标题,因此这不会给我标题。
我该怎么办?
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 标题并跳过它的效果 其余的。
如果可以选择 Perl:
perl -ne 'print if $. > 1 or ! $h; $h=1; close ARGV if eof' *.csv > master.csv
$.
是行号。close ARGV if eof
。$h
记录标题是否已打印。
就像每个使用该线程接受的解决方案的人(也像我一样:))的旁注 - 请注意,如果标题包含新行,即类似
的内容,此代码将会失败column1,"column\nwith\new line",column2
value1,value2,value3
...
在这种情况下,只有
column1,"column
部分将被视为标题,标题的其余部分将被视为普通行(这将完全破坏您的最终 CSV)。如果您的标头内部有新行,我能想到的唯一解决方案是使用“成熟的”csv 阅读器库,它将能够正确读取标头。
但是尽管有这个小问题,上面的行让我免于很多头痛。 :D
实现此目的的另一种便捷方法是使用
csvkit
包。
首先,安装包
sudo apt install csvkit
接下来,运行 csvstack
命令:
csvstack myFile1.csv myFile2.csv > myCombinedOutputFile.csv
您还可以合并 2 个以上的文件。每个文件可以包含一个标头。仅使用第一个文件中的标头并将其包含在输出文件中。
<?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"); ?>