我有三组不同的文件,如下所示:
cat "110001_test file_first_file.csv"
ID,NAME,LOCATION
1,Vikrant,Gurgaon
2,Bharat,Noida
3,Raju,Hyderabad
cat "110001_test file_second_file.csv"
ID,NAME,LOCATION
1,Vikrant,Gurgaon
22,abcd,Noida
3,Raju,Hyderabad
cat "110001_test file_third_file.csv"
ID,NAME,LOCATION
1,Vikrant,Gurgaon
2,Bharat,Noida
33,xyz,Hyderabad
我使用下面的命令将这些文件合并在一起,并将标题保留在顶部一次,并删除重复项(如果有)。
find . -type f -name '*test file*.csv' -exec cat {} + | awk 'NR == 1; NR > 1 {print $0 | "sort -u"}' > output.file
它给我的输出为:
ID,NAME,LOCATION
1,Vikrant,Gurgaon
22,abcd,Noida
2,Bharat,Noida
33,xyz,Hyderabad
3,Raju,Hyderabad
ID,NAME,LOCATION
我了解这里发生了什么以及指挥部正在做什么。它基本上忽略第一行并选择其他记录来排序并删除其中的重复项。因此,我在输出文件的底部看到一个额外的标头。
我期待这样的输出。
ID,NAME,LOCATION
1,Vikrant,Gurgaon
22,abcd,Noida
2,Bharat,Noida
33,xyz,Hyderabad
3,Raju,Hyderabad
答案1
使用,和:bash
head
tail
sort
您可以将文件名保存在数组中,然后
- 打印第一个文件的标题行
- 输出从第 2 行开始的所有文件的内容以及
sort
带有 unique 选项的结果 - 将输出重定向到文件
files=( *test*.csv )
{
head -n1 "${files[0]}"
for i in "${files[@]}"; do
tail -n+2 "$i"
done | sort -u
} > output
答案2
您不能依赖NR>1
在所有文件之前使用和连接
cat {} +
像这样,我尝试尽可能重用您的代码:
{
awk 'NR==1{print;exit}' *test*file*csv
find . -type f -name '*test*file.csv' -exec awk 'NR>1' {} \; |
sort -u
} > output.file
输出文件
ID,NAME,LOCATION
1,Vikrant,Gurgaon
22,abcd,Noida
2,Bharat,Noida
33,xyz,Hyderabad
3,Raju,Hyderabad
查找-exec {} +
-exec command {} +
-exec 操作的此变体对所选文件运行指定的命令,但命令行是通过在末尾附加每个所选文件名来构建的
所以已经串联起来了
答案3
只需执行以下操作:
find . -type f -name '*test*file.csv' -exec awk '!seen[$0]++' {} +
对于 awk 读取的每一行,如果它之前没有(!)在称为的关联数组中设置见过它将被添加到数组中,并且由于条件结果解析为“true”,因此该行将输出,如果 awk 读取任何同一行,则条件结果为“false”,因此它将跳过重复项;
在 awk$0
中指的是整行,这里我们用作数组键,并且值将针对每个键(行)读取而递增。对于一行,如果它没有在数组中设置,则值为 0 并将被打印,如果键的值 >0 它将被跳过。
答案4
稍微修改一下你的命令行,我们将得到所需的输出:
awk 'NR<2||FNR>1' ./*test_file*.csv > temp ;
( head -n 1; sort -u; ) < temp > output.file
您的结果位于文件 output.file 中