使用bash,sed或awk拆分CSV文件并排除输出中的列

时间:2012-04-18 20:43:40

标签: linux bash csv sed awk

我有一个CSV文件,其中包含以下数据: -

1,275,,,275,17.3,0,"2011-05-09 20:21:45"
2,279,,,279,17.3,0,"2011-05-10 20:21:52"
3,276,,,276,17.3,0,"2011-05-11 20:21:58"
4,272,,,272,17.3,0,"2011-05-12 20:22:04"
5,272,,,272,17.3,0,"2011-05-13 20:22:10"
6,278,,,278,17.3,0,"2011-05-13 20:24:08"
7,270,,,270,17.3,0,"2011-05-13 20:24:14"
8,269,,,269,17.3,0,"2011-05-14 20:24:20"
9,278,,,278,17.3,0,"2011-05-14 20:24:26"

此文件包含4432986行数据。

我希望在最后一栏的日期基于新文件名拆分文件。

因此,基于上面的数据,我希望每个文件中每天有6个新文件行。

我想要以YYYY_MM_DD格式命名的文件。

我还想忽略输出数据中的第一列

因此,文件2011_05_13将包含以下行,并排除第一列: -

272,,,272,17.3,0,"2011-05-13 20:22:10"
278,,,278,17.3,0,"2011-05-13 20:24:08"
270,,,270,17.3,0,"2011-05-13 20:24:14"

我打算在linux机器上执行此操作,因此使用任何Linux实用程序的任何内容都会很酷,请使用awk等等吗?

6 个答案:

答案 0 :(得分:5)

以下是awk中的单行代码:

awk -F "," '{ split ($8,array," "); sub ("\"","",array[1]); sub (NR,"",$0); sub (",","",$0); print $0 > array[1] }' file.txt

实现了所需的输出,尽管这些代码中的某些代码可能会更加简洁。 HTH。

编辑:

从左到右阅读代码:

  • -F ","
    是的,这设置了分隔符。

  • split ($8,array," ")
    这将拆分空间上的第八列,并将此信息放入名为array的数组中。

  • sub ("\"","",array[1])
    我们取第一个数组元素(这是一个将成为我们的输出文件名的切片)并替换掉前导"符号(我们需要转义"符号,所以我们放{{1前面的角色)。

  • \
    这样可以方便地从文件开头删除行号(sub (NR,"",$0)是行号,NR当然是划分前的整行输入)。

  • $0
    这将删除行号后面的逗号。

  • 现在我们有一个干净的文件名和干净的数据行,我们可以将sub (",","",$0)写入$0array[1]

FIX:

因此,如果您更喜欢下划线而不是下划线,我们需要解决的是print $0 > array[1]。我刚刚添加了全局替换:array[1]

更新的代码是:

gsub ("-","_",array[1])

HTH。

答案 1 :(得分:2)

您可以使用此awk命令:

awk -F, 'BEGIN{OFS=",";} {dt=$8; gsub(/^"| .*"$/,"", dt);
$1=""; sub(/^,/, "", $0); print $0 > dt}' input.txt

答案 2 :(得分:1)

脚本语言(perl / python)可能是你最好的选择,但我喜欢在bash中做这个的挑战,所以在这里。

 cat bigfile.txt | while read LINE;
  do echo $LINE >> `echo $LINE | cut -d, -f8 | cut -c2-11`.txt ;
 done

基本上,它的作用是在while循环中逐行读取文件,然后根据日期将该行附加到文件中。

使用两个cut命令的组合拉出日期。第一个cut使用逗号分隔符(-d,)关闭最后一列(第8列),然后第二个cut通过删除第一个"来提取日期,然后匆匆走向11号角色。


现在,要解决第一栏的删除问题:

cat bigfile.txt | sed 's/^.*?,//'

这个正则表达式只删除第一个逗号之前的所有内容。

所以,我们将用这个替换while循环的开头,留下我们:

 cat bigfile.txt | sed 's/^.*?,//' | while read LINE;
  do echo $LINE >> `echo $LINE | cut -d, -f8 | cut -c2-11`.txt ;
 done

答案 3 :(得分:1)

这个怪物会抓取所有唯一日期,然后在原始文件中抓取这些键的greps,将它们保存到由该键命名的文件中。是的,无用的猫,但试图雾化行动。

cat records.txt \
| cut -f8 -d, \
| cut -f1 -d ' ' \
| tr -d '"' \
| sort -u \
| while read DATE ; do \
    cat records.txt \
    | cut -f2- -d, \
    | egrep ",\"${DATE} [0-9]{2}:[0-9]{2}:[0-9]{2}\"" \
    > ${DATE}.txt
done

答案 4 :(得分:0)

一定很简单

$ sed 's/^[0-9]*,//' your_gigantic_data.csv

答案 5 :(得分:0)

这可能对您有用:

sed 's/^[^,]*,\(.*"\(....\)-\(..\)-\(..\).*\)/echo \1 >>\2_\3_\4.csv/' file | sh

或GNU sed:

sed 's/^[^,]*,\(.*"\(....\)-\(..\)-\(..\).*\)/echo \1 >>\2_\3_\4.csv/e' file