두 개의 CSV 파일이 있습니다.
이것은 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
이것은 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
제목(필드 2에 있음)과 일치하도록 허용하는 이 코드가 있습니다.
cat $csv1 |cut -d, -f2 | while read p; do
grep -i "$p" $csv2
if [ $? -eq 0 ];then
grep -i "$p" $csv1
fi
done
현재 이 코드는 csv1의 각 행을 살펴보고, csv2에 일치하는 헤더가 있는 행이 있으면 일치하는 행을 함께 인쇄합니다. 이것은 정말 잘 작동합니다.
하지만 이제 정확한 제목을 검색하는 대신 3개 이상의 단어가 일치하는지 확인하도록 스크립트를 조정하고 싶습니다.
따라서 이 페이지의 csv 데이터 출력은 다음과 같습니다.
11, The Sun Still Shines in Reading, 64312, 464566
69, The Sun Shines, 6464, 52364
97, Reading Still Shines, 545464, 16748967
여기에는 csv1의 맨 위 행이 포함되고 그 뒤에 필드 2(제목)에 3개 이상의 일치하는 단어가 있는 csv2의 두 행이 포함됩니다. 일치하는 단어 수를 지정하는 방법은 무엇입니까?
편집: 내가 언급하는 것을 잊은 한 가지는 csv1의 행 수가 csv2의 크기보다 훨씬 작다는 것입니다(예: 수천 개에 비해 10개). 생각해 보면 가장 큰 데이터를 정의할 수 있으므로 중요하지 않은 것 같습니다. 설정은 csv1 또는 csv2입니다.
답변1
perl
아마도 좀 더 쉘 중심적인 솔루션(awk?)이 있을 것입니다. 그러나 문제가 복잡해지면 저는 보통 그것을 사용합니다. 이것은 모든 것을 csv2
메모리로 읽어 들여 행을 해시의 키로 수집하는 Perl 스크립트입니다. 해당 값은 해당 헤더입니다.
그런 다음 을 반복하고 csv1
제목을 꺼낸 다음 의 각 제목에 대해 csv2
제목의 각 단어가 나타나는 횟수를 계산합니다. 더 큰 경우 desired
일치하는 헤더와 해당 헤더의 "소스" 줄을 인쇄합니다 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;