Combinando 3 ou mais palavras de campos em arquivos csv separados

0

Eu tenho dois arquivos csv:

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

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

Eu tenho este código que permite a correspondência de 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, esse código examina cada linha no csv1 e, se houver uma linha no csv2 que tenha um título correspondente, ela imprimirá as linhas correspondentes juntas. Isso funciona muito bem.

No entanto, gostaria de adaptar o script para que, em vez de pesquisar um título exato, ele verifique se há três ou mais palavras correspondentes.

Assim, 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 de csv1 no topo, seguida pelas duas linhas de 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 eu esqueci de mencionar é que csv1 será significativamente menor em tamanho em termos de linhas de csv2 (como 10 comparar com milhares), embora pensando nisso eu acho que isso não importa realmente como eu posso definir o maior conjunto de dados como csv1 ou csv2.

    
por nmh 18.05.2016 / 16:09

1 resposta

2

Pode haver uma solução mais centrada em shell (awk?), mas eu geralmente recorro a perl quando o problema se torna complexo. Aqui está um script perl que lê todos os 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, em seguida, para cada título de csv2 , conta o número de vezes que cada palavra no título é vista. Se for mais de desired , o título correspondente será impresso, juntamente com a linha "source" 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;
    
por 18.05.2016 / 17:07