【发布时间】:2016-09-04 01:24:41
【问题描述】:
我有一个脚本,它逐行读取 csv 文件,并将字段 2 中的标题与另一个 csv 文件进行比较。如果 5 个或更多单词匹配,它会打印出每个文件中与此条件匹配的行。这是脚本:
#!/bin/perl
#subroutine for discovering year
sub find_year {
my( $str ) = @_;
my $year = $1 if( $str =~ /\b((?:19|20)\d\d)\b/ );
return $year
}
#####CREATE CSV2 DATA
my @csv2 = ();
open CSV2, "<csv2" or die;
@csv2=<CSV2>;
close CSV2;
my %csv2hash = ();
my @csv2years;
for ( @csv2 ) {
chomp;
my ($title) = $_ =~ /^.+?,\s*([^,]+?),/; #/define the data which is the title
$csv2hash{$_} = $title; # Indicate that title data will input into csv2hash.
}
###### CREATE CSV1 DATA
open CSV1, "<csv1" or die;
while (<CSV1>) {
chomp; #removes new lines
my ($title) = $_ =~ /^.+?,\s*([^,]+?),/; #/ creates variable of title
my %words;
$words{$_}++ for split /\s+/, $title; #/ get words
## Collect unique words into an array- the @ means an array
my @titlewords = keys(%words);
# Add exception words which shouldn't be matched.
my @new;
foreach my $t (@titlewords){
push(@new, $t) if $t !~ /^(rare|vol|volume|issue|double|magazine|mag)$/i;
}
###### The comparison algorithm
@titlewords = @new;
my $desired = 5; # Desired matching number of words
my $matched = 0;
foreach my $csv2 (keys %csv2hash) {
my $count = 0;
my $value = $csv2hash{$csv2};
foreach my $word (@titlewords) {
my @matches = ( $value=~/\b$word\b/ig );
my $numIncsv2 = scalar(@matches);
@matches = ( $title=~/\b$word\b/ig );
my $numIncsv1 = scalar(@matches);
++$count if $value =~ /\b$word\b/i;
if ($count >= $desired || ($numIncsv1 >= $desired && $numIncsv2 >= $desired)) {
$count = $desired+1;
last;
}
}
if ($count >= $desired) {
print "$csv2\n";
++$matched;
}
}
print "$_\n\n" if $matched;
}
如您所见,我创建了一个 find_year 子例程,可用于发现标题是否包含 20 世纪或 21 世纪(19xx 或 20xx)的年份。几天前我问了一个问题,这可以让我将结果分配给涉及匹配年份的一组条件,Borodin 在这里提供了一个很好的答案。
Perl- What function am I looking for? Assigning multiple rules to a specified outcome
我希望现在应用相同的条件,只是这次脚本将比较 csv 标题中的日期,而不是标准输入和数据列表(如上一个问题)。
我现在要做的是将此逻辑作为一个函数包含在我的单词匹配脚本中,这样如果我之前的问题中满足的条件被认为是通过,那么执行脚本的单词匹配部分(即 5 个单词匹配) .如果它们符合失败条件,则跳过比较行并移至下一行(即不要打扰脚本的 5 个匹配单词元素)。 Pass 和 Fail 的结果不必打印出来,我只是用这些词来描述我上一个问题中年份比较条件的规则。
csv1 示例:
14564564,1987 the door to the other doors,546456,47878787
456456445,Mullholland Drive is the bets film ever 1959,45454545,45454545
456456445,The Twin Peaks forget that stuff,45454545,45454545
454654564, 1939 hello good world you are great ,45456456, 54564654
csv2 示例:
154465454,the other door was the door to 1949,546456,478787870
2156485754,Mullholland Drive is the bets film ever 1939,45454545,45454545
87894454,Twin Peaks forget that stuff 1984,45454545,45454545
2145678787, 1939 good lord you are great ,787425454,878777874
year_match 子程序合并前的当前结果:
2156485754,Mullholland Drive is the best film ever 1939,45454545,45454545
456456445,Mullholland Drive is the best film ever 1959,45454545,45454545
87894454,Twin Peaks forget that stuff 1984,45454545,45454545
456456445,The Twin Peaks forget that stuff,45454545,45454545
2145678787, 1939 good lord you are great ,787425454,878777874
454654564, 1939 hello good world you are great ,45456456, 54564654
match_year 子程序合并后的期望结果:
87894454,Twin Peaks forget that stuff 1984,45454545,45454545
456456445,The Twin Peaks forget that stuff,45454545,45454545
2145678787, 1939 good lord you are great ,787425454,878777874
454654564, 1939 hello good world you are great ,45456456, 54564654
我可以理解 Borodin 对我之前的问题的回答,但是由于我正在编写的这个脚本很难阅读(无论如何是 IMO 新手意见!),我无法弄清楚如何将这个新的在其中发挥作用。
【问题讨论】:
-
你必须学会发布简短的问题
-
诚然,这是一个问题,但脚本需要完整地存在,不幸的是我无法解释发生了什么,抱歉!
-
您应该将问题简化为更简单的问题,否则,我担心有人会有时间了解整个脚本、问题和您的要求
-
$numIncsv1 >= $desired- 奇怪的测试。如果在一个标题中发现一个单词不止一次,则计为 N 个单词或一个? -
经过深思熟虑,这是我一直在努力解决的问题。我想要它,以便每个单词必须在另一个文件中匹配才能被视为匹配,但目前如果一个 csv 有,例如
the3 次,另一个有the一次,在desired中计数为 3,这是我需要解决的单独问题。