基于csv中比较列的特定数量的行的高级串联

时间:2014-09-15 11:02:14

标签: bash csv awk sed compare

这是基于previous解决问题的问题。 我有以下类型的.csv文件(它们不是全部排序!,但列的结构是相同的):

name1,address1,town1,zip1,email1,web1,,,,category1
name2,address2,town2,zip2,email2,,,,,category2
name3,address3,town3,zip3,email3,,,,,category3_1
name3,address3,town3,zip3,,,,,,category3_2
name3,address3,town3,zip3,,,,,,category3_3
name4,address4,town4,zip4,,,,,,category4_1
name4,address4,town4,zip4,email4,,,,,category4_2
name4,address4,town4,zip4,email4,,,,,category4_3
name4,address4,town4,zip4,,,,,,category4_4
name5,address5,town5,zip5,,,,,,category5_1
name5,address5,town5,zip5,,web5,,,,category5_2
name6,address6,town6,zip6,,,,,,category6
  • 列中的前4个记录总是被填充,其他列并不总是,除了最后一个 - 类别
  • “,”分隔符之间的空格意味着没有特定行或名称的数据
  • 如果nameX不包含addressX但是addressY,则它是一个不同的记录(不是同一行),不应该连接

我需要 sed awk 中的脚本,也许是 bash (但这个解决方案在较大的文件上要慢一点[数百MB + ]),将前4列(在这种情况下)比较它们,如果匹配,将每个类别合并为“;”分隔符,并将结构和最可能的数据保存在.csv文件的那些匹配行的其他列中:

name1,address1,town1,zip1,email1,web1,,,,category1
name2,address2,town2,zip2,email2,,,,,category2
name3,address3,town3,zip3,email3,,,,,category3_1;category3_2;category3_3
name4,address4,town4,zip4,email4,,,,,category4_1;category4_2;category4_3;category4_4
name5,address5,town5,zip5,,web5,,,,category5_1;category5_2
name6,address6,town6,zip6,,,,,,category6

如果不可能,解决方案可能是保留数据的第一行(带有categoryX_1的数据)。例如:

name1,address1,town1,zip1,email1,web1,,,,category1
name2,address2,town2,zip2,email2,,,,,category2
name3,address3,town3,zip3,email3,,,,,category3_1;category3_2;category3_3
name4,address4,town4,zip4,,,,,,category4_1;category4_2;category4_3;category4_4
name5,address5,town5,zip5,,,,,,category5_1;category5_2
name6,address6,town6,zip6,,,,,,category6

在使用脚本之前是否必须对.csv进行排序?

再次感谢你!

2 个答案:

答案 0 :(得分:0)

sed -n 's/.*/²&³/;H
$ { g
:cat
  s/\(²\([^,]*,\)\{4\}\)\(\([^,]*,\)\{5\}\)\([^³]*\)³\(.*\)\n\1\(\([^,]*,\)\{5\}\)\([^³]*\)³/\1~\3~ ~\7~\5;\9³\6/
  t fields
  b clean
:fields
  s/~\([^,]*\),\([^~]*~\) ~\1,\([^~]*~\)/\1,~\2 ~\3/
  t fields
  s/~\([^,]*\),\([^~]*~\) ~\([^,]*,\)\([^~]*~\)/\1\3~\2 ~\4/
  t fields
  s/~~ ~~//g

  b cat

:clean
  s/.//;s/[²³]//g
  p
  }' YourFile

Posix版本(所以--posix使用GNU sed)并且之前没有对文件进行排序

在缓冲区中加载完整文件后添加2个递归循环,添加标记以便于操作,并使用sed组替换获得很多乐趣(希望只能达到可用的最大组)。

  1. 循环以添加类别(每行一行后需要下一个循环所需的1行)和一个临时结构的大子字段(来自2个连接行的2组字段。字段5到9是1组)
  2. 将子字段取消组合到原始位置
  3. 最后,删除标记和第一个新行

    假设没有²³~字符因为用作标记(您可以使用其他标记并使用新标记调整脚本)

    注意:

    • 对于一百MB文件的性能,我猜awk会更有效率。
    • 对数据进行排序可能有助于提高性能,减少每个类别循环后要操作的数据量

答案 1 :(得分:0)

我发现,这个特殊问题通过数据库处理得更快......

SQL - GROUP BY to combine/concat a column

db:mysql to wamp