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 perl
cuando el problema se vuelve tan complejo. Aquí hay un script en Perl que lee todo csv2
en 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;