2

我有一个巨大的数据集,比如 15 - 20 GB,它是一个制表符分隔的文件。虽然我可以在 Python 或 SQL 中执行此操作,但在 Shell 脚本中执行此操作以避免移动 csv 文件会更容易和简单

说,例如,采用管道分隔的文件输入:

----------------------------------------
Col1 | Col2 | Col3 | Col4 | Col5 | Col6
----------------------------------------
 A   |  H1  | 123  | abcd | a1   | b1   
----------------------------------------
 B   |  H1  | 124  | abcd | a2   | b1   
----------------------------------------
 C   |  H2  | 127  | abd  | a3   | b1   
----------------------------------------
 D   |  H1  | 128  | acd  | a4   | b1   
----------------------------------------

SQL 查询看起来像

从其中 col2='H1' 选择 Col1、Col4、Col5、Col6

输出:

--------------------------
Col1 | Col4 | Col5 | Col6
--------------------------
 A   | abcd | a1   | b1   
--------------------------
 B   | abcd | a2   | b1   
--------------------------
 D   | acd  | a4   | b1   
--------------------------

然后,我只需要取其中的 Col4 来做一些字符串解析并在 OutputFile1 下输出:

--------------------------------
Col1 | Col4 | Col5 | Col6 | New1
--------------------------------
 A   | abcd | a1   | b1   | a,b,c,d
--------------------------------
 B   | abcd | a2   | b1   | a,b,c,d
--------------------------------
 D   | acd  | a4   | b1   | a,c,d
--------------------------------

Col4 是一个 URL。我需要解析 URL 参数。参考问题 -如何在 shell 脚本中解析 URL 参数

我想知道我是否还有另一个文件

文件2:

--------------
ColA | ColB | 
--------------
 A   | abcd | 
--------------
 B   | abcd | 
--------------
 D   | qst  | 
--------------

我需要为 ColB 生成类似的解析输出。

输出文件2:

--------------
ColA | ColB | New1
--------------
 A   | abcd | a,b,c,d
--------------
 B   | abcd | a,b,c,d
--------------
 D   | qst  | q,s,t
--------------

用于合并 OutputFile1 和 OutputFile2 的 SQL 查询将对

OutputFile1.Col1 = OutputFile2.ColA 和 OutputFile1.New1 = OutputFile2.New1

最终输出:

--------------------------------
Col1 | Col4 | Col5 | Col6 | New1
--------------------------------
 A   | abcd | a1   | b1   | a,b,c,d
--------------------------------
 B   | abcd | a2   | b1   | a,b,c,d
--------------------------------

请分享实施相同的建议。

主要限制是文件的大小。

谢谢

4

2 回答 2

3

在http://open-innovation.alcatel-lucent.com/projects/unity/上有一个非常简单的数据库管理程序,名为“unity”,适用于 UNIX 。在统一中,您有 2 个主要文件:

  1. 一个你喜欢的数据文件,例如“foo”,和
  2. 一个描述符文件,与数据文件具有相同的基本名称,但前缀为“D”表示描述符,例如“Dfoo”

这些都是简单的文本文件,您可以使用您喜欢的任何编辑器进行编辑(或者它有自己的名为 uedit 的数据库感知编辑器)。

Dfoo 将在 foo 中的每一列都有一行,描述出现在 foo 中该列中的数据的属性,并且它是与下一列的分隔符。

foo 会有数据。

自从我在 raw 中使用 unity 已经有一段时间了(我有在幕后使用它的脚本)但是对于上面显示的第一个表:

----------------------------------------
Col1 | Col2 | Col3 | Col4 | Col5 | Col6
----------------------------------------
 A   |  H1  | 123  | abcd | a1   | b1   
----------------------------------------
 B   |  H1  | 124  | abcd | a2   | b1   
----------------------------------------
 C   |  H2  | 127  | abd  | a3   | b1   
----------------------------------------
 D   |  H1  | 128  | acd  | a4   | b1   
----------------------------------------

描述符文件(Dfoo)将类似于:

Col1 | 5c
Col2 | 6c
Col3 | 6c
Col4 | 6c
Col5 | 6c
Col6 \n 6c

并且数据文件(foo)将是:

A|H1|123|abcd|a1|b1
B|H1|124|abcd|a2|b1
C|H2|127|abd|a3|b1
D|H1|128|acd|a4|b1

然后,您可以运行统一命令,例如:

uprint -d- foo

打印表格,其中的行由下划线和在描述符文件中指定的宽度的单元格分隔(例如 6c = 6 个字符居中,而 6r = 6 个字符右对齐)。

uselect Col2 from foo where Col3 leq abd

从列 Col2 中选择值,其中 Col3 中的对应值在词法上等于字符串“abd”。

有统一的命令可以让您执行连接、合并、插入、删除等操作 - 基本上是您希望能够对关系数据库执行的任何操作,但这一切都只是基于简单的文本文件。

统一起来,您可以在每列之间指定不同的分隔符,但如果所有分隔符都相同(除了最后一个分隔符将是 '\n'),那么您也可以在文件上运行 awk 脚本,只需使用 awk -F 和分隔器。

您可以查看的其他几个工具集可能更容易安装,但可能没有统一(自 1970 年代以来一直存在!)那么多的功能,将是 recutils(来自 GNU)和 csvDB,所以你的完整作业/研究清单是:

请注意,recutils 具有用于在 recutils 和 CSV 格式之间进行转换的 rec2csv 和 csv2rec 工具。

于 2013-04-02T13:32:51.093 回答
2

对于管道分隔文件:

awk '$2=="H1"{y="";x=$4;for(i=1;i<=length($4);i++)y=y?y","substr(x,i,1):substr(x,i,1);print $1,$4,$5,$6,y;}' FS="|" OFS="|" file

对于制表符分隔的文件,将 FS 留空:

awk '$2=="H1"{y="";x=$4;for(i=1;i<=length($4);i++)y=y?y","substr(x,i,1):substr(x,i,1);print $1,$4,$5,$6,y;}'  OFS="\t" file
于 2013-04-02T12:05:45.600 回答