【问题标题】:Merging two csv files, can't get rid of newline合并两个csv文件,无法摆脱换行符
【发布时间】:2019-06-13 20:49:02
【问题描述】:

我正在合并两个 csv 文件。为简单起见,我只显示相关的列。两个文件中的列都多于四列。

file_a.csv

col2, col6, col7, col17
a, b, c, 145
e, f, g, 101
x, y, z, 243

file_b.csv

col2, col6, col7, col17
a, b, c, 88
e, f, g, 96
x, k, l, 222

输出应如下所示:

col2, col6, col7, col17, col18
a, b, c, 145, 88
e, f, g, 101, 96

所以当 col2、col6 和 col7 的内容匹配时,file_b 的 col17 作为 col18 添加到 file_a。

我试过这个:

awk -F, 'NR == FNR {a[$2,$6,$7] = $17;next;} {if (! (b = a[$2,$6,$7])) b = "N/A";print $0,FS,b;}' file_a.csv file_b.csv > out.csv

输出如下:

col2, col6, col7, col17, 
 , col18
a, b, c, 145
 , 88
e, f, g, 101
 , 96

因此,我尝试添加的 file_b 中的第 17 列确实被添加了,但显示在新行上。

我认为这是因为file_a和file_b的每一行后面都有回车。在 Notepad++ 中,我可以看到 CRLF。但我无法摆脱它们。另外,我宁愿不经过两个步骤:首先摆脱回车然后合并。相反,如果我可以在合并期间绕过回车,它会快得多。

另外,如果您能告诉我如何去掉分隔合并列的逗号前后的空格,我将不胜感激。请注意,为了更好的可读性,我在列之间放置了空格,并在其他列中放置了逗号。实际文件中的情况并非如此。但是合并文件中col17和","和col18之间确实有空格,不知道为什么。

如果您坚持将此标记为重复,请在下面的评论中解释上一个问题的答案如何解决我的问题。我尝试从以前的类似问题中弄清楚,但失败了。

【问题讨论】:

    标签: csv awk merge text-processing


    【解决方案1】:

    请试试这个(GNU awk):

    awk -F, -v RS="[\r\n]+" 'NR == FNR {a[$2,$6,$7] = $17;next;} {b=a[$2,$6,$7]; print $0 FS (b? b : "N/A")}' file_a.csv file_b.csv 
    

    你有问题的地方:
    1、回车,通过RS="[\r\n]+",它将多个换行符,包括\r\n作为行分隔符。请注意,这也会忽略空行,如果您不想这样做,请更改为 RS="\r\n"
    2.空格,那是因为awk默认的OFS是空格。当您打印时,您使用了,,这将在它们之间添加空格。只需使用空间或有时将它们写在一起就可以了,它们将被连接起来。

    【讨论】:

      【解决方案2】:

      请您尝试关注一下。

      awk -v RS="[\r\n]+" '
      BEGIN{
        SUBSEP=OFS=", "
      }
      FNR==NR{
        if(FNR==1){
          header=$0
        }
        a[$1,$2,$3]=$4
        next
      }
      FNR==1 && FNR!=NR{
        split(header,array,", ")
        sub(/[a-zA-Z]+/,"",array[4])
        print header,"col"array[4]+1
        next
      }
      a[$1,$2,$3]{
        print $0,a[$1,$2,$3]
      }' b.csv a.csv
      

      上面的代码做了什么:

      1- 似乎您的 Input_file(s) 中可能有回车符,所以我将 \r\n 作为记录分隔符(如果您想删除回车符,请尝试 tr -d '\r < a.csv > temp && mv temp a.csv 并为其他字段执行)。

      2- 这也会根据文件的最后一列创建标题。

      【讨论】:

        【解决方案3】:

        与米勒 (http://johnkerl.org/miller/doc)

        mlr --csv join -j col2,col6,col7 --lp l --rp r -f file_a.csv \
        then unsparsify --fill-with "" \
        then rename lcol17,col17,rcol17,col18 file_b.csv
        

        你有

        col2,col6,col7,col17,col18
        a,b,c,145,88
        e,f,g,101,96
        

        我已用作输入

        # file_a.csv
        
        col2,col6,col7,col17
        a,b,c,145
        e,f,g,101
        x,y,z,243
        
        # file_b.csv
        
        col2,col6,col7,col17
        a,b,c,88
        e,f,g,96
        x,k,l,222
        

        【讨论】:

        • 我不认为“加入”允许基于多列匹配 csv,除非您连接这些列。您可能已经在上面这样做了,但我不熟悉加入代码,因此无法确定。感谢您尝试回答我的问题。
        • 这是米勒内部的连接,它基于多列进行匹配。请尝试一下
        【解决方案4】:

        由于您想在分隔符 , 之间获取空格,您可以尝试这个 Perl 解决方案,它会在拆分时删除空格。

        答案假设您在文件中有\r。我已经使用cat-vT 选项来显示回车符存在

        $ cat -vT file_a.csv
        col2, col6, col7, col17^M
        a, b, c, 145^M
        e, f, g, 101^M
        x, y, z, 243^M
        $ cat -vT file_b.csv
        col2, col6, col7, col17^M
        a, b, c, 88^M
        e, f, g, 96^M
        x, k, l, 222^M
        $
        
        $ perl -lne  'BEGIN { %kv=map{chomp;chop;@a=split(/\s*,\s*/);"$a[0],$a[1],$a[2]"=>"$a[3]"} qx(cat file_b.csv) } chop;@b=split(/\s*,\s*/);$x="$b[0],$b[1],$b[2]"; print "$x,$b[-1],",$kv{$x} if $kv{$x} ' file_a.csv
        col2,col6,col7,col17,col17
        a,b,c,145,88
        e,f,g,101,96
        $
        

        【讨论】:

          猜你喜欢
          • 2020-03-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-12-14
          • 2023-03-04
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多