使用简单模式匹配逐行比较文件

时间:2015-05-04 14:11:43

标签: regex perl pattern-matching string-matching

我有两个文件:在第一个文件中,每一行都有一些与之关联的标签;第二个文件包含属于某些类别的标签。

File1 - 标有行:

I have never had an issue.  L_102 ----- L_127
I travel overseas and offer a lot of services that are very useful to me    L_105 ----- L_134 ----- L_148
Expense to have L_522
Great benefits  L_148
prestige    L_118

File2 - 标签落在的类别:

Issues:113,114,115,116,127
Benefits:105,220,154,543,590
General:148,134,154

我编写了一个Perl脚本来从第一个文件中获取标签。

#!/usr/bin/perl

use strict;
use warnings;

my $file = shift || "INPUTFILE";
my $outputfile = shift || "OUTPUTFILE";

open my $fh, '<', $file or die "Can not open '$file': $!";
open( OUTFILE, ">", $outputfile) or die "Can not open '$outputfile': $!";

while(my $w = <$fh>) {
    my @matches = $w =~ m/(L_[0-9][0-9][0-9])/g;
    for(@matches){s/L_//g;
    s/\s+/\t/g;
    }
    print OUTFILE "@matches\n";
}

第一个脚本的输出是:

102 127
105 134 148
522
148
118

我有第二个Perl脚本来从第二个文件(包含类别)中获取级别:

#!/usr/bin/perl

use strict;
use warnings;

my $file = shift || "INPUTFILE";
my $outputfile = shift || "OUTPUTFILE";
my $patern = shift ||"Issues:"

open my $fh, '<', $file or die "Can not open '$file': $!";
open( OUTFILE, ">", $outputfile) or die "Can not open '$outputfile': $!";

while(my $var = <$fh>) {
if(my @matches =$var=~/(.*$patern.*)/)
{
for(@matches){s/$patern//g;s/\,/\t/g}
print OUTFILE "@matches\n";
}
}

第二个脚本的第二个输出是:

113 114 115 116 127

现在我想逐行匹配第一个输出和第二个输出。 我想要的结果是:如果第二个输出中的任何数字与第一个输出中的任何一行匹配,那么我想打印1;否则如果该行没有匹配打印-1。

以上输出如下:

 1
-1
-1
-1
-1

1 个答案:

答案 0 :(得分:1)

这将您的两个脚本合二为一。它读取指向$inputfile的{​​{1}}文件句柄,根据正则表达式("INPUTFILE.txt")或$regexp中存在的搜索键查找匹配项哈希值。

由于匹配很简单,我们使用的正则表达式是使用%patternsjoin和所需的搜索字符串构建的。在替代方法(这里注释掉)中,我们使用哈希键本身来检查搜索模式是否存在。

我已经更改了|语句中的变量和文件名,因为大写的文件名使它们看起来像旧式文件句柄:

open

以上脚本应该有效。您可以从上一个#!perl -l my $inputfile = "INPUTFILE.txt"; my $outputfile = "OUTPUTFILE.txt"; my $matchfile = "MATCHFILE.txt"; open my $inputfh, '<', $inputfile or die "No file '$inputfile': $!"; open my $matchfh, '<', $matchfile or die "No file '$matchfile': $!\n"; open my $outfh, '>', $outputfile or die "No file '$outputfile': $!\n"; my %patterns; while (<$matchfh>) { $patterns{$_} = () for map { split /,/, $_ } /Issues:(.*)/; } my $regex = join "|", keys %patterns; $regex = qr/$regex/; # create a regex from %patterns print "Search patterns : ", join " ", keys %patterns; print "Regex : $regex \n"; while (my $line = <$inputfh>) { chomp $line; # Print "1" for 3 digits matching search pattern; "-1" otherwise: #print exists $patterns{$_} ? "1" : "-1" for $line =~ m/(\d\d\d)/g; # Print "1" if a matching pattern is on a line; -1 otherwise: if (grep /$regex/, $line) { # print "1 - $line"; } else { print "-1 - $line"; } } 语句中删除- $line并添加文件句柄目标(print)以将输出定向到文件。

由于$outfh中有五行,因此输出为:

inputfile

NB 可以使用"ternary operator"Search patterns : 127 116 114 115 113 Regex : (?^:127|116|114|115|113) 1 - I have never had an issue. L_102 ----- L_127 -1 - I travel overseas ... very useful to me L_105 ----- L_134 ----- L_148 -1 - Expense to have L_522 -1 - Great benefits L_148 -1 - prestige L_118 )将最终if ... else块缩短为:

<cond> ? 1 : 0

如果 print $line =~ /$regex/ ? '1' : '-1'; 评估为“true”(或“1”),则会打印“1”;如果评估为“假”(或“0”),则将打印“$line =~ /$regex/”。

如果您从两个文件中读取并只是将输出重定向到shell,则所有这些的简短版本将是:

-1