合并具有相同 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
跳过不必要地读取不匹配的文件
我需要将目录中具有相同 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