合并具有相同 header 的 csv 文件:使用 xargs 将多个文件传递给 awk

Merge csv files with same header: passing multiple files to awk with xargs

我需要将目录中具有相同 header(第一行)的所有 csv 文件合并在一起。假设我们有:

文件a.txt:

head1,head2,head3
1,2,"abc"
8,42,"def"

文件b.txt:

head4,head2
"aa",2

文件c.txt:

head1,head2,head3
12,2,"z"
15,2,"z"

如果我想要所有 header "head1,head2,head3" 的文件,那么它应该合并文件 a 和 c 并生成:

awk 'FNR==1 && NR!=1{next;}{print}' a.txt c.txt 
head1,head2,head3
1,2,"abc"
8,42,"def"
12,2,"z"
15,2,"z"

现在,对于给定的 header,我可以检测要自动合并的文件,但我无法将生成的列表传递给 awk。我正在使用以下命令:

head -n1 -v * | grep -B1 "head1,head2,head3" | awk "/==>/{ print $2 }" | xargs -l -0 awk 'FNR==1 && NR!=1{next;}{print}'
awk: fatal: cannot open file `a.txt
c.txt
' for reading (No such file or directory)

其中 head 列出文件名和第一行,grep 仅保留匹配的 headers(以及前面行中带有 -B1 的关联文件名),并且第一次调用 awk 只保留文件名,每行一个。 我也试过了(添加 tr '\n' ' '):

head -n1 -v * | grep -B1 "head1,head2,head3" | awk "/==>/{ print $2 }" | tr '\n' ' ' | xargs -l -0 awk 'FNR==1 && NR!=1{next;}{print}'                       
awk: fatal: cannot open file `a.txt c.txt ' for reading (No such file or directory)

我最终尝试了以下方法(改为使用 tr '\n' '[=22=]'):

head -n1 -v * | grep -B1 "head1,head2,head3" | awk "/==>/{ print $2 }" | tr '\n' '[=17=]' | xargs -l -0 awk 'FNR==1 && NR!=1{next;}{print}'                            
head1,head2,head3
1,2,"abc"
8,42,"def"
head1,head2,head3
12,2,"z"
15,2,"z"

(虽然我不确定 [=23=] 是如何解释的),至少这个命令有效,但看起来每个文件都由 awk 单独处理,因为 header 是打印两次。

我错过了什么?

这有帮助吗?

$ awk -v h='head1,head2,head3' 'BEGIN{print h} FNR==1{f=[=10=]==h?1:0; next} f' *.txt
head1,head2,head3
1,2,"abc"
8,42,"def"
12,2,"z"
15,2,"z"
  • -v h='head1,head2,head3' 保存 header 行以签入变量 h
  • BEGIN{print h} 打印 header(假设至少有一个文件匹配)
  • FNR==1{f=[=14=]==h?1:0; next} set/clear 根据文件第一行匹配内容的标志 h
  • f 如果设置了标志则打印
  • *.txt 要合并的文件列表


使用 GNU awk,您可以使用 FNR==1{if([=18=]!=h) nextfile; next} 1

跳过不必要地读取不匹配的文件