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 perl
quando o problema fica tão complexo. Aqui está um script Perl que lê tudo csv2
na 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;