Correspondência de 3 ou mais palavras de campos em arquivos CSV separados

Correspondência de 3 ou mais palavras de campos em arquivos CSV separados

Eu tenho dois arquivos csv:

Este é 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

Este é 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

Tenho esse código que permite a correspondência dos títulos (que estão no campo 2).

cat $csv1 |cut -d, -f2 | while read p; do
  grep -i "$p" $csv2
  if [ $? -eq 0 ];then
    grep -i "$p" $csv1
  fi
done

No momento, este código analisa cada linha em csv1 e, se houver uma linha em csv2 que tenha um título correspondente, ele imprime as linhas correspondentes juntas. Isso funciona muito bem.

No entanto, gostaria agora de adaptar o script para que, em vez de procurar um título exato, verifique se há 3 ou mais palavras correspondentes.

Portanto, a saída no caso dos dados csv nesta página seria:

11, The Sun Still Shines in Reading, 64312, 464566
69, The Sun Shines, 6464, 52364
97, Reading Still Shines, 545464, 16748967

Que consiste na linha do csv1 na parte superior, seguida pelas duas linhas do csv2 que possuem 3 ou mais palavras correspondentes no campo 2 (o título). Como posso especificar o número de palavras correspondentes?

EDIT: Uma coisa que esqueci de mencionar é que o csv1 será significativamente menor em tamanho em termos de linhas do que o csv2 (como 10 em comparação com milhares), embora pensando bem, acho que isso realmente não importa, pois posso definir os maiores dados definido como csv1 ou csv2.

Responder1

Pode haver uma solução mais centrada no shell (awk?), Mas geralmente recorro perlquando o problema fica tão complexo. Aqui está um script Perl que lê tudo csv2na memória, coletando as linhas como chaves em um hash cujos valores são os títulos correspondentes.

Em seguida, ele percorre csv1, extrai o título e, para cada título de csv2, conta o número de vezes que cada palavra do título é vista. Se for maior que desired, o título correspondente será impresso, juntamente com a linha "fonte" de 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;

informação relacionada