Hacer coincidir 3 o más palabras de campos en archivos csv separados

Hacer coincidir 3 o más palabras de campos en archivos csv separados

Tengo dos archivos csv:

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

Tengo este código que permite la coincidencia de títulos (que están en el 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

Por el momento, este código examina cada línea en csv1, y si hay una línea en csv2 que tiene un título coincidente, imprime las líneas coincidentes juntas. Esto funciona muy bien.

Sin embargo, ahora me gustaría adaptar el script para que, en lugar de buscar un título exacto, verifique si coinciden 3 o más palabras.

Entonces, el resultado en el caso de los datos csv de esta página sería:

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

Que consta de la línea de csv1 en la parte superior, seguida de las dos líneas de csv2 que tienen 3 o más palabras coincidentes en el campo 2 (el título). ¿Cómo puedo especificar el número de palabras coincidentes?

EDITAR: Una cosa que olvidé mencionar es que csv1 será significativamente más pequeño en tamaño en términos de líneas que csv2 (como 10 en comparación con miles), aunque pensándolo bien, supongo que esto realmente no importa, ya que puedo definir los datos más grandes. establecido como csv1 o csv2.

Respuesta1

Puede haber una solución más centrada en el shell (¿awk?), pero normalmente recurro a ella perlcuando el problema se vuelve tan complejo. Aquí hay un script en Perl que lee todo csv2en la memoria, recopilando las líneas como claves en un hash cuyos valores son los títulos correspondientes.

Luego recorre csv1, extrae el título y luego, para cada título de csv2, cuenta el número de veces que se ve cada palabra del título. Si es mayor que desired, se imprime el título coincidente, junto con su línea "fuente" 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;

información relacionada