匹配单独 csv 文件中字段中的 3 个或更多单词

匹配单独 csv 文件中字段中的 3 个或更多单词

我有两个 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 中的行,后跟 csv2 中的两行,它们在字段 2(标题)中具有 3 个或更多匹配单词。如何指定匹配单词的数量?

编辑:我忘记提到的一件事是,csv1 的行数比 csv2 的大小要小得多(就像 10 与数千相比),尽管考虑一下,我想这并不重要,因为我可以定义最大的数据设置为 csv1 或 csv2。

答案1

perl可能有一个更以 shell 为中心的解决方案(awk?),但当问题变得如此复杂时我通常会转向。这是一个 perl 脚本,它将所有内容读csv2入内存,将行作为键收集到散列中,其值是相应的标题。

然后循环遍历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;

相关内容