【问题标题】:Create "smart" csv file using shell script使用 shell 脚本创建“智能”csv 文件
【发布时间】:2015-12-04 13:22:49
【问题描述】:

我有一个 txt 文件,其中包含以下格式的一些记录:

Name=Kevin
Age=33
Gender=M
Street=LA Road
Occupation=Service
Name=Josh
Age=22
Gender=M
Occupation=None
Name=Sarah
Street=First Avenue
Occupation=Administrator
...

如您所见,我有一组不同的属性,一个接一个地识别某些人,但并非所有属性都可以为所有人设置。 将始终设置的唯一属性是 Name 值,因此我可能会将其用作分隔符(因为不同的 Name 值之间的每个值肯定会引用 Name 值中的第一个)。

我想从上面的文件中生成一个csv文件如下

文件:output.csv ->

Name;Age;Gender;Street;Occupation
Kevin;33;M;LA Road;Service
Josh;22;M;<**BLANK**>;None
Sarah;<**BLANK**>;<**BLANK**>;First Avenue;Administrator
...

你能帮我写一个 shell/perl 脚本吗,因为我想把这些数据上传到数据库表中。

【问题讨论】:

  • 编辑:只能使用 bash,抱歉打错了
  • 什么数据库?大多数 RDMS 都具有允许您在配置某种控制文件后按原样加载数据的工具。附言点击编辑按钮编辑您的帖子以修正错字。
  • @Gary_W 问题说这些数据在文本文件中。
  • 您确定Name 将始终是记录的first 字段吗?为什么只能使用 bash?
  • @Jordan 是的,它们包含的数据将加载到什么数据库中?

标签: bash csv


【解决方案1】:

这对于awk 来说看起来很简单; perl 可能有点矫枉过正:

awk -F= 'BEGIN {OFS=";"; print "Name;Age;Gender;Street;Occupation"}
         $1=="Name"{if(name)print name,a,g,s,o;
           name=$2; a=g=s=o="<**BLANK**>"}
         $1=="Age"        {a=$2}
         $1=="Gender"     {g=$2}
         $1=="Street"     {s=$2}
         $1=="Occupation" {o=$2}
         END {if(name)print name,a,g,s,o}'

【讨论】:

    【解决方案2】:

    下面创建了一个表,当我们收到新的键/值对时向右增长,并在我们看到“名称”关键字时向下增长。优点是除了“名称”之外,脚本中没有对关键字的硬编码期望——它只是在看到新事物时适应和扩大表格。

    #! /usr/bin/awk -f
    BEGIN {
            FS  = "="
            OFS = ";"
            key = 1
            val = 2
            split("", head)
            split("", table)
            row = 0
            col = 0
            name = 0
            blank = "<**BLANK**>"
    }
    NF == 2 {
            if (!name && $key != "Name")
                    table[0,head["Name"]=col++] = "Name"
            name = 1
            if (!($key in head)) {
                    for (i=1; i<=row; i++)
                            table[i, col] = blank
                    table[0,head[$key]=col++] = $key
            }
            if ($key == "Name") {
                    row++
                    for(i=0; i<col; i++)
                             table[row,i] = blank
            table[row,head[$key]] = $val
    }
    END {
            for (i=0; i<=row; i++) {
                    if (!col)
                            break
                    x = table[i,0]
                    for (j=1; j<col; j++)
                            x = x OFS table[i,j]
                    print x
            }
    }
    

    输出如下:

    Name;Age;Gender;Street;Occupation
    Kevin;33;M;LA Road;Service
    Josh;22;M;<**BLANK**>;None
    Sarah;<**BLANK**>;<**BLANK**>;First Avenue;Administrator
    

    【讨论】: