我应该替换cat, sed和排序命令来整理多个csv文件的时间戳在脚本中,也使用awk?


  1. 我想根据每个源csv文件(ts.csv, x.csv, y.csv和z.csv在这个例子中)的第一列的时间戳整理一大批csv文件。所有csv文件的行数相同
  2. 在csv被整理之前,当它们被写入整理后的。csv时,我希望每一行在前面都有一些额外的信息:行号,FILENAME(没有。csv),时间戳。
  3. 时间戳应该来自ts.csv文件的第二列(每行都有不同的时间戳)。为了澄清ts.csv有两个时间戳,第一列有用于整理所有文件的时间戳,第二列有添加到所有其他文件的时间戳。这个第三部分已经解决了,感谢Ed Norton在这个问题

对于其他部分,我稍微修改了他的脚本以打印额外的字段,并将另一行添加到我的bash脚本

cat out/*.csv | sed s/.csv// | sort -t, -nk4 > out/collated.csv

是完整的脚本:

!/bin/bash
rm out/*      
mkdir -p out  
awk '
BEGIN { FS=OFS="," }
NR==FNR {
map[FNR] = $2
next
}
FNR==1 {
close(out)
out = "out/" FILENAME
}
{ print FNR, FILENAME, map[FNR], $0 > out }
' ts.csv *.csv
cat out/*.csv | sed s/.csv// | sort -t, -nk4 > out/collated.csv

是否有更好的方法来做cat, sed和sort命令正在做的事情?也许是awk的一部分?因为我可以有50-500个csv文件,每个文件可以有数万行,所以我担心未来的性能。我想知道有什么更好的方法来做到这一点?

另外,我怎样才能摆脱输出文件中只包含头的前4行,因为它们基本上与文件名相同。

这些是我的示例输入文件:

```
$ cat x.csv
time,x
1.1,7.6
2.12,7.5
3.1,7.1
$ cat y.csv
time,y1,y2,y3
1.11,1,1,1
2.22,2,2,2
3.23,3,3,3
$ cat z.csv
time,z1,z2
1.03,1,4
2.41,2,5
3.13,3,6
$ cat ts.csv 
time,t1
1.11,4.7
2.21,5.8
3.31,6.2
````

和我当前的输出:

cat out/collated.csv 
1,ts,t1,time,t1
1,x,t1,time,x
1,y,t1,time,y1,y2,y3
1,z,t1,time,z1,z2
2,z,4.7,1.03,1,4
2,x,4.7,1.1,7.6
2,ts,4.7,1.11,4.7
2,y,4.7,1.11,1,1,1
3,x,5.8,2.12,7.5
3,ts,5.8,2.21,5.8
3,y,5.8,2.22,2,2,2
3,z,5.8,2.41,2,5
4,x,6.2,3.1,7.1
4,z,6.2,3.13,3,6
4,y,6.2,3.23,3,3,3
4,ts,6.2,3.31,6.2

更新:这是在Raman的建议后更新的脚本:

!/bin/bash
rm out2/*.csv
mkdir -p out2
awk '
BEGIN { FS=OFS="," }
NR==FNR {
map[FNR] = $2
next
}
FNR==1 {
close(out)
out = "out2/" FILENAME
}
{ print map[FNR], $0 > out }
' ts.csv *.csv
awk -F, '
BEGIN { cnt++ } # counter for row number in original csv, skip 1 for header 
FNR != 1 { # Skip the headers
map[$1][$0]=FILENAME # Create 2 dimensional array with the timestamp as the first index and the line the second. 
#The file name is the value
} 
END { 
PROCINFO["sorted_in"]="@ind_str_asc"; # At the end of processing the files, set the array ordering.
for (i in map) { 
cnt++; # Increment the counter
for (j in map[i]) { 
split(map[i][j],map1,"[./]"); # Loop through the the array and strip the ".csv" out of the filenames
print cnt","map1[2]","j # Print the data required
} 
} 
}' out2/*.csv > out2/collated.csv

您的输出与示例输入不匹配,但请尝试以下操作(使用GNU awk进行数组排序):

awk -F, 'FNR != 1 { map[$1][$0]=FILENAME } END { PROCINFO["sorted_in"]="@ind_str_asc";for (i in map) { cnt++;for (j in map[i]) { split(map[i][j],map1,".");print cnt","map1[1]","j } } }' *.csv > out/collated.csv

解释:

awk -F, 'FNR != 1 { # Skip the headers
map[$1][$0]=FILENAME # Create 2 dimensional array with the timestamp as the first index and the  line the second. The file name is the value
} 
END { 
PROCINFO["sorted_in"]="@ind_str_asc"; # At the end of processing the files, set the array ordering.
for (i in map) { 
cnt++; # Increment a counter
for (j in map[i]) { 
split(map[i][j],map1,"."); # Loop through the the array and strip the ".csv" out of the filenames
print cnt","map1[1]","j # Print the data required
} 
} 
}' *.csv > out/collated.csv

相关内容

  • 没有找到相关文章

最新更新