均衡csv数据中的列数

时间:2015-03-04 16:00:27

标签: csv awk sed

我正在从转换为csv的PDF文件中解析一些联系人数据,这导致每行基于缺少的条目计算不同的列数。

有没有办法使用sed,awk,cut等来纠正这个问题,方法是确保一些易于模式化的列匹配 - 确保电子邮件地址在可用时位于相同的列中,其他像“Lifetime成员”电子邮件不可用时“或”访客“?

第一列是个人/公司的名称,但其余的是任意的。重点是提取联系信息(如电子邮件,电话号码等),并在可用时将其放在相同的列中。 我的想法是检查电子邮件是否在第6列,如果没有,则在它之前添加一些空列等

示例数据:

Steve Smith;9828;1;+1234 567 2345;Guest;steve@example.org;1;1 12th st;48572 Nowhere
Steve Jobs;+1234 567 2345;noreply@example.org;1;48572 Nowhere
John Smith;9828;1;+1234 567 2345;Lifetime member;1;1 23rd st;48572 Nowhere
Peter Blavounius;2312;peter@blavounius.com

通缉输出:

Steve Smith;9828;1;+1234 567 2345;Guest;steve@example.org;1;1 12th st;48572 Nowhere
Steve Jobs;+1234 567 2345;;;;noreply@example.org;1;;48572 Nowhere
John Smith;9828;1;+1234 567 2345;Lifetime member;1;1 23rd st;48572 Nowhere
Peter Blavounius;2312;;;;peter@blavounius.com

1 个答案:

答案 0 :(得分:3)

这会让你开始,但它还没有完成,你还需要确定其他领域,到目前为止我所做的只是找出几个领域来向你展示方法:

$ cat tst.awk
BEGIN {
    FS=OFS=";"
    ARGV[ARGC] = ARGV[ARGC-1]
    ARGC++
}

{
    name = tel = email = digs4 = ""
    for (i=1;i<=NF;i++) {
        if (i == 1) {
            name=$i; $i=""; nameFld = 1
        }
        else if ($i ~ /^\+/) {
            tel=$i; $i=""; telFld = (i > telFld ? i : telFld)
        }
        else if ($i ~ /@/) {
            email=$i; $i=""; emailFld = (i > emailFld ? i : emailFld)
        }
        else if ($i ~ /^[0-9]{4}$/) {
            digs4=$i; $i=""; digs4Fld = (i > digs4Fld ? i : digs4Fld)
        }
    }
    maxFlds = (NF > maxFlds ? NF : maxFlds)
}

NR>FNR {
    for (i=1;i<=maxFlds;i++) {
        if (i == nameFld)       { $i = name }
        else if (i == telFld)   { $i = tel }
        else if (i == emailFld) { $i = email }
        else if (i == digs4Fld) { $i = digs4 }
        else { $i = $i } # make sure null fields are present
    }
    print
}

$ awk -f tst.awk file
Steve Smith;9828;1;+1234 567 2345;Guest;steve@example.org;1;1 12th st;48572 Nowhere
Steve Jobs;;;+1234 567 2345;48572 Nowhere;noreply@example.org;;;
John Smith;9828;1;+1234 567 2345;Lifetime member;;1 23rd st;48572 Nowhere;
Peter Blavounius;2312;;;;peter@blavounius.com;;;

它会对您的输入文件进行2次传递 - 第一次识别与每个正则表达式匹配的最大字段编号,因为您希望每个匹配该正则表达式的字段出现在输出中,第二个用于标识字段,清除他们在记录中的位置,然后将每个字段放在正确的位置。

你可以通过将它的上下文与上面的正则表达式或者它在行中的固定位置(例如,人名总是在字段1中)或者它与其他东西的相对位置(例如单个)相匹配来识别字段的含义。在电子邮件地址之前或之后/第3个字段编号之前/之后发生的数字或....)

希望它有意义。添加一些printfs并稍微玩一下,如果你在那之后感到困惑就会问问题。