如何使用awk / shell脚本来执行SQL Where子句和SQL连接,如过滤和合并行和列?

时间:2013-04-02 11:54:22

标签: shell awk gawk

我有一个巨大的数据集,例如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查询看起来像

SELECT Col1,Col4,Col5,Col6 FROM WHERE col2 ='H1'

输出:

--------------------------
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参数。请参阅问题 - How to parse URL params in shell script

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

File2:

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

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

OutputFile2:

--------------
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
--------------------------------

请分享建议以实施相同的目标。

主要限制因素是文件的大小。

由于

2 个答案:

答案 0 :(得分:3)

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

  1. 一个名为您喜欢的数据文件,例如“foo”和
  2. 描述符文件,其具有与数据文件相同的基本名称,但对于描述符具有前缀“D”,例如, “Dfoo”
  3. 这些都是简单的文本文件,您可以使用您喜欢的任何编辑器进行编辑(或者它拥有自己的数据库感知编辑器,名为uedit)。

    对于foo中的每一列,Dfoo都会有一行描述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中的对应值是词汇式EQual,字符串为“abd”。

    有一些统一命令可以让你进行连接,合并,插入,删除等等 - 基本上你希望能够对关系数据库做什么,但它只是基于简单的文本文件。

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

    你可以看到的其他几个工具集可能更容易安装,但可能没有Unity统一的功能(自20世纪70年代以来一直存在!)将是recutils(来自GNU)和csvDB所以你的完整的家庭作业/研究清单是:

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

答案 1 :(得分: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