将 N 个 csv 文件连接到一个 csv 文件

将 N 个 csv 文件连接到一个 csv 文件

我需要构建一个 shell 脚本,它将所有可用的 CSV 文件连接成一个。所有这些 CSV 文件都具有相似的结构(即相同的标题和列数),并且这些文件具有共同的前缀GFP

例如:有一天我可能会有以下文件,

GFP_20210609.csv
GFP_20210610.csv

或者有时我可能有很多这样的文件。这里的问题是我不确定一天会出现多少个这样的文件(假设每天不超过 5 个 CSV 文件)。

我是 shell 脚本编写的新手。任何帮助将不胜感激。

sed 1d GFP_20210610.csv > GFP_20210610_NO_HEADER.csv
cat GFP_20210609.csv GFP_20210610_NO_HEADER.csv > GFP_FINAL.csv

答案1

尝试awk

awk 'NR==1||FNR>1' GFP*.csv > output.csv

这将从第二行开始打印每个文件的所有行(FNR>1意味着每个文件的行计数器大于一)以抑制重复的标题,但请务必打印遇到的第一行(NR==1),这是第一个文件的标题行文件。

然后输出被重定向到一个文件output.csv

该语法利用了这样一个事实:awk如果在规则块 ( ) 之外找到的条件{ ...}为 true,则将打印当前行。在这种情况下,我们可以完全省略规则块,因为我们实际上不想编辑,而只想过滤输入文件。

答案2

首先,我们将创建一次头文件,并将其保留在与其余 csv 文件相同的文件夹中

head -qn 1 GFP_20210609.csv > common.header

common_header.csv包含您选择的任何 csv 文件的第一行(根据您所说,所有 csv 文件都具有相同的标题)。您应该构建此文件一次并将其保留在同一目录中以供进一步使用。

head命令首先输出n文本文件的行,在我们的头文件情况下为“1”。

tail命令输出最后n文本文件的行。从“1”开始,我们将忽略所有 csv 文件的第一行,因为我们希望避免标头重复。

额外的 -q(安静)参数,headtail防止我们在最终文件中不需要的额外输出信息。

下一行是脚本的源代码:

cat common.header > FINAL.csv && tail -qn 1 GFP_*.csv >> FINAL.csv

两个命令cattail都与 a 连接,&&表示 tail将运行仅有的如果cat命令成功。

(*) 注意:tail -qn 1...也可以写成tail -q -n 1...和 是同一件事。

答案3

使用perl我们在每个 eof 条件下显式关闭文件句柄,这是为了重置行计数器。对于绝对第一行,我们使用任何标量变量 $nr 并对其进行预递增。

perl -lne 'print if
  ++$nr==1||$.>1;
  eof && close(ARGV);
' GFP_*.CSV > total.csv

GNU sed-s单独处理文件的分离流选项一起使用。

{
head -n 1 "$(printf '%s\n' GFP_*.CSV |head -n 1 -)"
sed -se 1d GFP_*.csv
} > total.csv

相关内容