Saya telah menggunakan skrip perl ini (terima kasih kepada Jeff Schaller) untuk mencocokkan 3 atau lebih kata dalam bidang judul dari dua file csv terpisah seperti yang dijawab di sini:
Mencocokkan 3 atau lebih kata dari bidang dalam file csv terpisah
Scriptnya adalah:
#!/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;
Sejak itu saya menyadari bahwa saya ingin mengabaikan kata-kata tertentu di antara judul-judul dan tidak mengklasifikasikannya sebagai kata-kata yang cocok. Saya telah menggunakan sed untuk menghapusnya sebelum file csv dibandingkan tetapi ini tidak ideal karena saya kehilangan data dalam proses. Bagaimana saya bisa menambahkan kata-kata yang akan dianggap sebagai pengecualian untuk skrip perl ini? Sebagai contoh, katakanlah jika saya ingin skrip mengabaikan tiga kata yang terpisah and
if
dan the
ketika mencocokkan judul sehingga mereka akan menjadi pengecualian dari aturan.
perl
naskah dalam jawaban saya di bawah ini juga menjawab pertanyaan Anda baru saja dihapus. Theget_intersection
Metode dariList::Compare
modul menghilangkan entri ganda (yang adalah apa yang Anda harapkan dari set persimpangan), kata-kata individu dihitung hanya sekali untuk setiap judul. Ini adalah salah satu manfaat besar menggunakan modul perpustakaan yang ada daripada menulis sendiri - mereka biasanya menyertakan fitur yang berguna yang akan membutuhkan banyak upaya untuk mengimplementasikan diri Anda. Mereka juga cenderung telah menyelesaikan sebagian besar atau semua masalah umum (dan banyak yang tidak terlalu umum) terkait dengan tugas yang dihadapi.Jawaban:
Setelah garis
tambahkan kode untuk menghapus kata-kata dari array:
sumber
i
bendera ke pola. Saya mengedit jawaban saya untuk menunjukkannya.Hal ini sangat mirip dengan jawaban @ meuh ini, tapi bukannya menambahkan
foreach
lingkaran setelahsplit
line, Anda hanya perlu menambahkan satu baris ada, baik menggunakanperl
'sgrep
fungsi atau nyamap
fungsi:atau
Lihat
perldoc -f grep
danperldoc -f map
untuk detail lebih lanjut tentang fungsi-fungsi ini dan perbedaan di antara mereka. Mereka biasanya digunakan (terutamamap
) dalam banyakperl
skrip, jadi ada baiknya meluangkan waktu untuk memahami apa yang mereka lakukan dan mempelajari cara kerjanya.BTW, JANGAN gunakan
#!/usr/bin/env perl
. Menggunakanenv
seperti itu cukup dengan burukpython
danruby
skrip (di mana itu, sayangnya, konvensi), tapi itu benar-benar rusak untukperl
script dan pasti tidak dengan cara konvensional untuk menjalankannya.perl
memiliki banyak opsi baris perintah yang mengubah perilakunya dalam cara yang signifikan, tergantung pada jenis program yang Anda coba tulis. Menggunakanenv
untuk menjalankan juru bahasa sepertiperl
benar - benar menghancurkan kemampuan untuk meneruskan opsi baris perintah ke juru bahasa (karenaenv
tidak mendukungnya.env
Bahkan tidak dirancang untuk digunakan untuk tujuan ini, melakukannya hanya peretasan jelek yang mengambil keuntungan dari efek samping darienv
tujuan aktual - yaitu mengatur variabel lingkungan sebelum menjalankan program).Gunakan
#!/usr/bin/perl
sebaliknya (atau apa pun jalan menujuperl
penerjemah Anda ).Berikut skrip perl lain yang melakukan apa yang Anda inginkan - tetapi ini menggunakan skrip
Class::CSV
danList::Compare
modul, serta dua Hash-of-Array untuk membandingkan file CSV:Keluaran:
Setiap kelompok kecocokan diurutkan dan, meskipun output sampel tidak menunjukkannya (karena hanya ada satu kelompok kecocokan), masing-masing kelompok dicetak sebagai paragraf terpisah (yaitu dipisahkan oleh baris kosong)
BTW, jika Anda tidak ingin tanda kutip ganda di sekitar bidang judul, edit
my $key=join(...)
baris yang menambahkannya sehingga tidak.sumber