不完整的CSV文件(缺少列)

时间:2017-08-03 10:10:51

标签: shell csv awk sed gawk

我有一个CSV文件,在此CSV中,列中缺少一些条目。如果未设置列,我想添加空值。

以下是CSV文件的结构:

  

ID; LON; LAT;图像;历史;地址;文本;类型;名称;网络; DATE_OF_BIRTH; date_of_death;起始日期

完整的数据行如下所示:

  

n3329319394; 4.369872; 50.866430;历史=纪念馆;图像=文件:Schaerbeek_40_rue_Vondel_Les_pavés_de_la_mémoire.jpg;纪念:ADDR = 40,   Rue Vondel - Vondelstraat,Schaerbeek;纪念馆:text = Ici habitait   Elisabeth Orcher-KarolinskiNée1912resistanterrêtée15.8.1942   interneeMalinesdéportée18.8.1942Auschwitzassassinée   20.8.1942; memorial:type = stolperstein; name = Elisabeth Orcher-Karolinski; network = Stolpersteine   布鲁塞尔;人:DATE_OF_BIRTH = 1912-00-00;人:date_of_death = 1942年8月20日

但有时数据行看起来像这样:

  

n4208925477; 5.041860; 52.141352;历史=纪念馆;纪念:ADDR = Langegracht   27;纪念:type = stolperstein; name = Lucas& Clara IJzerman

知道如何轻松转换这些数据吗?一个好的提示可能是限定词:“image = ...”等。

谢谢, 比约恩

1 个答案:

答案 0 :(得分:0)

[投诉]

  • 你没有自己动手。
  • 您对问题的描述并不准确。

[投诉]

但你提出了我的好奇心。因此,我试图解决它。 (特别是,在你的样本数据中提到Stolperstein - 非常聪明。现在,我感觉像是一个“帮助好人”的使命......)

我简化了你的问题:

  1. 我认为字段idlonlat是强制性的。

  2. 我考虑了可选的命名字段namehistoricimage

  3. 我的测试数据test-complete-lines.txt

    n3329319394;4.369872;50.866430;name=Klaus Mustermann;historic=memorial;image=j.doe-de.png
    n3329319395;4.369872;50.866430;name=Gabi Mustermann
    n4208925477;5.041860;52.141352;historic=memorial
    n4208925477;5.041860;52.141352;image=the-image.png
    n3329319395;4.369872;50.866430;name=Gabi Mustermann;historic=memorial
    n3329319395;4.369872;50.866430;name=Gabi Mustermann;image=j.doe.female-de.png
    

    我的脚本test-complete-lines.awk

    BEGIN { FS=";" }
    # get mandatory fields id, lon, lat
    { id = $1 ; lon = $2 ; lat = $3 }
    # set optional fields empty
    { name=";name=" ; historic=";historic=" ; image=";image=" }
    # replace found fields with values
    /;name=/ { name = gensub(/^.*(;name=[^;]*).*$/, "\\1", "g", $0) }
    /;historic=/ { historic = gensub(/^.*(;historic=[^;]*).*$/, "\\1", "g", $0) }
    /;image=/ { image = gensub(/^.*(;image=[^;]*).*$/, "\\1", "g", $0) }
    # print processed line
    { print id";"lon";"lat""name""historic""image }
    

    使用gawk进行测试(bash,cygwin,Windows 10(64位)):

    $ awk --version
    GNU Awk 4.1.4, API: 1.1 (GNU MPFR 3.1.5-p10, GNU MP 6.1.2)
    Copyright (C) 1989, 1991-2016 Free Software Foundation.
    
    $ awk -f test-complete-lines.awk <test-complete-lines.txt 
    n3329319394;4.369872;50.866430;name=Klaus Mustermann;historic=memorial;image=j.doe-de.png
    n3329319395;4.369872;50.866430;name=Gabi Mustermann;historic=;image=
    n4208925477;5.041860;52.141352;name=;historic=memorial;image=
    n4208925477;5.041860;52.141352;name=;historic=;image=the-image.png
    n3329319395;4.369872;50.866430;name=Gabi Mustermann;historic=memorial;image=
    n3329319395;4.369872;50.866430;name=Gabi Mustermann;historic=;image=j.doe.female-de.png
    
    $
    

    注意:

    1. 替换找到的字段假定内容中不会显示;。我建议你制作一个计数器样本(内容中出现;)。这可能会激活某种引用或转义。因此,可能需要额外处理此类案件。

    2. 我只提到了一些指定的字段。您必须按照该方案添加其余部分。

    3. 顺便说一下。我在示例文本中意外地出了一个空行。这产生了:;;;name=;historic=;image=如果有必要处理空行,可能会插入另一条规则(BEGIN { }之后):
      /^[ \t]*$/ { skip }

    4. 在我的第一个版本中,我的示例数据中有一个拼写错误 - 遗忘;。因此,image=成为name=的内容,但也被认为是个别字段。假设命名字段可能不作为第一个字段出现,我将其修复为包括前面;字段名称的模式。