2つのCSVファイルがあります。
これはcsv1です。
11, The Sun Still Shines in Reading, 64312, 464566
13, You and Me Together Again London, 564564, 131355
12, What's the Story Now Your Gone, 4545646, 1124545
17, Hello I love you, 456899, 1259898
これはcsv2です。
69, The Sun Shines, 6464, 52364
12, Tell me your name, 56456, 21345
17, From London to New York, 897944, 234655
97, Reading Still Shines, 545464, 16748967
タイトル(フィールド2にあります)と一致することを可能にするこのコードがあります。
cat $csv1 |cut -d, -f2 | while read p; do
grep -i "$p" $csv2
if [ $? -eq 0 ];then
grep -i "$p" $csv1
fi
done
現在、このコードはcsv1の各行を調べ、csv2に一致するヘッダーを持つ行がある場合は一致する行を一緒に印刷します。これは本当にうまくいきます。
しかし、今では正確なタイトルを検索するのではなく、3つ以上の単語が一致することを確認するようにスクリプトを調整したいと思います。
したがって、このページのcsvデータ出力は次のようになります。
11, The Sun Still Shines in Reading, 64312, 464566
69, The Sun Shines, 6464, 52364
97, Reading Still Shines, 545464, 16748967
これには、csv1の一番上の行が含まれ、その後にフィールド2(タイトル)に3つ以上の一致する単語があるcsv2の2行が含まれます。一致する単語数を指定するには?
編集:私が言及することを忘れたことの1つは、csv1の行数がcsv2のサイズよりはるかに小さいことです(例:数千に比べて10個)。考えると、最大のデータを定義できるので重要ではないようです。設定はcsv1またはcsv2です。
ベストアンサー1
perl
おそらく、よりシェル中心のソリューション(awk?)があるでしょう。しかし、問題が複雑になると、私は通常それを使用します。これはすべてをcsv2
メモリに読み込み、行をハッシュのキーとして収集するPerlスクリプトです。その値は対応するヘッダーです。
次に、を繰り返してcsv1
タイトルを取り出し、次に、各タイトルについてcsv2
タイトルの各単語が表示される回数を計算します。大きい場合は、desired
一致するヘッダーとそのヘッダーの「ソース」行を印刷しますcsv1
。
#!/usr/bin/env perl
my @csv2 = ();
open CSV2, "<csv2" or die;
@csv2=<CSV2>;
close CSV2;
my %csv2hash = ();
for (@csv2) {
chomp;
my ($title) = $_ =~ /^.+?,\s*([^,]+?),/; #/ match the title
$csv2hash{$_} = $title;
}
open CSV1, "<csv1" or die;
while (<CSV1>) {
chomp;
my ($title) = $_ =~ /^.+?,\s*([^,]+?),/; #/ match the title
my @titlewords = split /\s+/, $title; #/ get words
my $desired = 3;
my $matched = 0;
foreach my $csv2 (keys %csv2hash) {
my $count = 0;
my $value = $csv2hash{$csv2};
foreach my $word (@titlewords) {
++$count if $value =~ /\b$word\b/i;
last if $count >= $desired;
}
if ($count >= $desired) {
print "$csv2\n";
++$matched;
}
}
print "$_\n" if $matched;
}
close CSV1;