CSVファイルのマージ、フィールド区切り記号も引用符で囲まれています。

CSVファイルのマージ、フィールド区切り記号も引用符で囲まれています。

3つのcsvファイルがあり、最初の列(id列)に結合したいと思います。

各ファイルには同じ3つの列があります。

ライン例:

id        | timestamp       |  Name

3792318, 2014-07-15 00:00:00, "A, B"

3つのcsvファイルを合わせるとき

join -t, <(join -t, csv1 csv2) csv3 > out.csv

ファイルout.csvの行ごとの列数が異なります。おそらく、区切り文字がコンマであり、一部の行(上記の例のように)には、セルの内容にコンマが含まれている可能性があります。

ベストアンサー1

明らかにcsvパーサーを使用する方が良いでしょうが、安全であると仮定できる場合

  1. 最初のフィールドにはカンマは含まれません。
  2. 最初のファイルに存在するIDのみが必要です(IDがfile2またはfile3にあるがfile1にはない場合は無視してください)。
  3. これらのファイルはRAMに収まるほど小さいです。

これにより、このPerlメソッドが機能します。

#!/usr/bin/env perl 
use strict;

my %f;
## Read the files
while (<>) {
    ## remove trailing newlines
    chomp;
    ## Replace any commas within quotes with '|'.
    ## I am using a while loop to deal with multiple commas.
    while (s/\"([^"]*?),([^"]*?)\"/"$1|$2"/){}
    ## match the id and the rest.
    /^(.+?)(,.+)/; 
    ## The keys of the %f hash are the ids
    ## each line with the same id is appended to
    ## the current value of the key in the hash.
    $f{$1}.=$2; 
}
## Print the lines
foreach my $id (keys(%f)) {
    print "$id$f{$id}\n";
}

上記のスクリプトを別の名前で保存し、次のfoo.plように実行します。

perl foo.pl file1.csv file2.csv file3.csv

上記のスクリプトは1行で書くこともできます。

perl -lne 'while(s/\"([^"]*?),([^"]*)\"/"$1|$2"/){} /^(.+?)(,.+)/; $k{$1}.=$2; 
           END{print "$_$k{$_}" for keys(%k)}' file1 file2 file3

おすすめ記事