我有一个如下所示的CSV文件(test.csv):
WH_01,TRAINAMS,A10,1221-ESD
WH_03,TRAINLON,L10A3,3005-21
WH_01,TRAINAMS,A101,PWR-120
WH_02,TRAINCLE,A1,074-HD-SATA
WH_01,TRAINAMS,A10,PWR-120
WH_02,TRAINCLE,A15,102-55665
WH_03,TRAINLON,L10A3,3005-20
WH_03,TRAINLON,UK-B3,101859
1)。我可以根据第2列中的值对文件进行排序,如下所示:
sort -t, -k2,2 test.csv > testsort.csv
2)。接下来,我想根据第2列中的值拆分文件。使用上面的示例,它应该创建3个文件:
testsort_1.csv:
WH_01,TRAINAMS,A10,1221-ESD
WH_01,TRAINAMS,A101,PWR-120
WH_01,TRAINAMS,A10,PWR-120
testsort_2.csv:
WH_02,TRAINCLE,A1,074-HD-SATA
WH_02,TRAINCLE,A15,102-55665
testsort_3.csv:
WH_03,TRAINLON,L10A3,3005-20
WH_03,TRAINLON,L10A3,3005-21
WH_03,TRAINLON,UK-B3,101859
我该怎么做?不知道是否需要排序,是否可以不进行排序即可达到以上目的。
谢谢。
答案 0 :(得分:2)
分开sort
和awk
的好举动。
$ sort -t, -k2,2 test.csv |awk -F, '!($2 in T) {T[$2]=++i} {print > ("testsort_" i ".csv")}'
$ tail -n +1 testsort*
==> testsort_1.csv <==
WH_01,TRAINAMS,A10,1221-ESD
WH_01,TRAINAMS,A101,PWR-120
WH_01,TRAINAMS,A10,PWR-120
==> testsort_2.csv <==
WH_02,TRAINCLE,A1,074-HD-SATA
WH_02,TRAINCLE,A15,102-55665
==> testsort_3.csv <==
WH_03,TRAINLON,L10A3,3005-20
WH_03,TRAINLON,L10A3,3005-21
WH_03,TRAINLON,UK-B3,101859
!($2 in T)
-如果在数组T
的索引中找不到第二个字段,{T[$2]=++i}
-递增计数器并将第二个字段保存为索引。{print}
-打印每一行> "file"
-覆盖,重定向并将输出附加到文件("." i ".")
-连接“字符串”和变量答案 1 :(得分:2)
由于您不确定是否需要排序几乎肯定意味着您不需要,并且您只是出于某种原因认为它很有用,而且您只是按$ 2排序,然后根据$ 2的价值,因此排序毫无用处。
您真正需要做的是:
O(n)
看:
awk -F, '{print > ($2".csv")}'
如果过去大约20个输出文件名并且未使用GNU awk,则每当$ 2更改时,您都必须关闭每个文件,并使用$ ls
test.csv
$ awk -F, '{print > ($2".csv")}' test.csv
$ ls
test.csv TRAINAMS.csv TRAINCLE.csv TRAINLON.csv
$ tail -n +1 TRAIN*
==> TRAINAMS.csv <==
WH_01,TRAINAMS,A10,1221-ESD
WH_01,TRAINAMS,A101,PWR-120
WH_01,TRAINAMS,A10,PWR-120
==> TRAINCLE.csv <==
WH_02,TRAINCLE,A1,074-HD-SATA
WH_02,TRAINCLE,A15,102-55665
==> TRAINLON.csv <==
WH_03,TRAINLON,L10A3,3005-21
WH_03,TRAINLON,L10A3,3005-20
WH_03,TRAINLON,UK-B3,101859
而不是>>
附加到他们。
如果出于某些原因您确实确实需要使用问题中的输出文件名,则为:
>
答案 2 :(得分:0)
您可以通过保持文件名计数器并使用sprintf
为每个连续文件组创建文件名,以相当简单的方式进行操作。您使用FNR
(文件记录号)来区分第一条记录和后续记录。
例如:
$ sort -t, -k2 file.csv |
awk -F, -v cnt=1 -v fn="testsort_1.csv" '
FNR==1 {
prev=$2
print $0 > fn
}
FNR>1 {
if ($2!=prev) {
cnt++
fn=sprintf("%s_%d.csv", "testsort", cnt)
}
print $0 > fn
prev=$2
}'
(注意:您将初始文件名设置为开始的变量,然后使用cnt
从sprintf
(计数)创建所有后续文件名。{{1 }}跟踪上一条记录的第二个字段。prev
是fn
和计数器创建的文件名。)
最初将sprintf
声明为变量的同一脚本的简短版本为:
prev
如果您不希望使用顺序编号的文件,而是希望从已排序的记录中提取sort -t, -k2 file.csv |
awk -F, -v cnt=0 -v prev="" '{
if ($2!=prev) {
cnt++
fn = "testsort_" cnt ".csv"
prev=$2
}
print $0 > fn
}'
,请查看@Cyrus现已删除的答案,该答案提供了一种出色(更短)的解决方案那方面。 (我看到您已经有了很好的答案)
使用/输出示例
使用您在"testsort_number.csv"
中的输入,将创建以下输出文件:
file.csv