使用简单的模式匹配逐行比较文件
Comparing files line by line using a simple pattern match
我有两个文件:在第一个文件中,每一行都有一些与之关联的标签;第二个文件包含属于特定类别的标签。
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
这会将您的两个脚本合二为一。它通读指向 "INPUTFILE.txt"
的 $inputfile
文件句柄,根据正则表达式 ($regexp
) 或 %patterns
中是否存在搜索键查找匹配项哈希。
由于匹配很简单,我们使用的正则表达式是使用 join
、|
和所需的搜索字符串构建的。在替代方法(此处已注释掉)中,我们使用哈希键本身来检查是否存在搜索模式。
我已经稍微更改了 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";
}
}
上面的脚本应该可以工作。您可以从最后的 print
语句中删除 - $line
并添加文件句柄目标 ($outfh
) 以将输出定向到文件。
由于inputfile
中有五行,输出为:
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
NB 最后的 if ... else
块可以使用 "ternary operator"(<cond> ? 1 : 0
) 缩短为:
print $line =~ /$regex/ ? '1' : '-1';
这样,如果 $line =~ /$regex/
的计算结果为 "true"(或“1”),将打印“1
”;如果计算结果为 "false"(或“0”),将打印“-1
”。
如果你从你的两个文件中读取并简单地使用你的 shell 重定向输出,所有这一切的简短版本将是:
#!perl -l
my $inputfile = "INPUTFILE.txt";
my $matchfile = "MATCHFILE.txt";
open my $inputfh, '<', $inputfile or die "No '$inputfile': $!";
open my $matchfh, '<', $matchfile or die "No '$matchfile': $!\n";
my %patterns;
while (<$matchfh>) {
$patterns{$_} = () for map { split /,/, $_ } /Issues:(.*)/;
}
my $regex = join "|", keys %patterns;
$regex = qr/$regex/;
while (my $line = <$inputfh>) {
chomp $line;
print $line =~ $regex ? '1' : '-1';
}
我有两个文件:在第一个文件中,每一行都有一些与之关联的标签;第二个文件包含属于特定类别的标签。
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
这会将您的两个脚本合二为一。它通读指向 "INPUTFILE.txt"
的 $inputfile
文件句柄,根据正则表达式 ($regexp
) 或 %patterns
中是否存在搜索键查找匹配项哈希。
由于匹配很简单,我们使用的正则表达式是使用 join
、|
和所需的搜索字符串构建的。在替代方法(此处已注释掉)中,我们使用哈希键本身来检查是否存在搜索模式。
我已经稍微更改了 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";
}
}
上面的脚本应该可以工作。您可以从最后的 print
语句中删除 - $line
并添加文件句柄目标 ($outfh
) 以将输出定向到文件。
由于inputfile
中有五行,输出为:
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
NB 最后的 if ... else
块可以使用 "ternary operator"(<cond> ? 1 : 0
) 缩短为:
print $line =~ /$regex/ ? '1' : '-1';
这样,如果 $line =~ /$regex/
的计算结果为 "true"(或“1”),将打印“1
”;如果计算结果为 "false"(或“0”),将打印“-1
”。
如果你从你的两个文件中读取并简单地使用你的 shell 重定向输出,所有这一切的简短版本将是:
#!perl -l
my $inputfile = "INPUTFILE.txt";
my $matchfile = "MATCHFILE.txt";
open my $inputfh, '<', $inputfile or die "No '$inputfile': $!";
open my $matchfh, '<', $matchfile or die "No '$matchfile': $!\n";
my %patterns;
while (<$matchfh>) {
$patterns{$_} = () for map { split /,/, $_ } /Issues:(.*)/;
}
my $regex = join "|", keys %patterns;
$regex = qr/$regex/;
while (my $line = <$inputfh>) {
chomp $line;
print $line =~ $regex ? '1' : '-1';
}