別のcsvファイル内のフィールドに3つ以上の単語を一致させます。

別のcsvファイル内のフィールドに3つ以上の単語を一致させます。

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;

おすすめ記事