String 比较2个哈希中的2个已处理密钥
我想在文件中读取一些符号,如“!”和“^”,并想在将它们与另一行的其他字符串进行比较之前删除它们。如果删除符号后两个字符串相同,我想将它们存储在另一个名为“common”的散列中。 例如 文件A: 文件B:String 比较2个哈希中的2个已处理密钥,string,perl,hash,String,Perl,Hash,我想在文件中读取一些符号,如“!”和“^”,并想在将它们与另一行的其他字符串进行比较之前删除它们。如果删除符号后两个字符串相同,我想将它们存储在另一个名为“common”的散列中。 例如 文件A: 文件B: hello help? oh no yes 在这种情况下,FileA和FileB应该是相同的,因为我正在比较字符到出现“!”或“^”的位置。 我使用以下代码读取文件: open FILEA, "< script/".$fileA or die; my %read_file; whil
hello
help?
oh no
yes
在这种情况下,FileA和FileB应该是相同的,因为我正在比较字符到出现“!”或“^”的位置。
我使用以下代码读取文件:
open FILEA, "< script/".$fileA or die;
my %read_file;
while (my $line=<FILEA>) {
(my $word1,my $word2) = split /\n/, $line;
$word1 =~ s/(!.+)|(!.*)|(\^.+)|(\^.*)//;#to remove ! and ^
$read_file{$word1} = $word1;
}
close(FILEA);
我试着用下面的例子测试我的替换和比较两个字符串,结果很好。我不知道为什么从文件中将字符串读入哈希不起作用
use strict;
use warnings;
my $str="hello^vsd";
my $test="hello";
$str =~ s/(!.+)|(!.*)|(\^.+)|(\^.*)//;
my %hash=();
$hash{$str}=();
foreach my $key(keys %hash)
{
print "$key\n";
}
print "yay\n" if exists $hash{$test};
print "boo\n" unless exists $hash{$test};
两个文件可以有不同数量的文本行,搜索时文本行的顺序不必相同。例如,“噢,不”可以出现在“hello”之前。您可以使用正则表达式字符类s/[?^]//g来删除“^”和“?”,请注意,^必须是组中的最后一个字符,否则需要转义它。(转义它可能更安全,以防以后添加其他字符,这样它们就不会被否定) 我处理所有文件,使用散列计算单词存在的文件 为了比较差异,我使用了2**(#of file),所以我得到了值2**0=1、2**1=2、2**2=4,依此类推。我用来显示字符串属于哪个文件。如果它们存在于所有文件中,它们将等于总文件数,因此在本例中,2-3(2+1)表示它们同时存在于两个文件中,1表示仅存在于文件A中,2表示存在于文件B中。您可以通过按位and(&)进行检查 编辑:添加了测试条件
<!-- language: perl -->
my @files = qw(FileA.txt FileB.txt);
my %words;
foreach my $i (0 .. $#files) {
my $file = $files[$i];
open(FILE,$file) or die "Error: missing file $file\n$!\n";
while (<FILE>) {
chomp;
next if /^$/;
my ($word) = split /[!\^]/;
$word =~ s/[?\^]//g; # removes ^ and ?
$words{$word} += 2**$i;
}
close(FILE);
}
my %common;
foreach my $key (sort keys %words) {
my @found;
foreach my $i (0 .. $#files) {
if ( $words{$key} & 2**$i ) { push @found, $files[$i] }
}
if ( $words{$key} & 2**$#files ) { $common{$key}++ }
printf "%10s %d: @found\n",$key,$words{$key};
}
my @tests = qw(hello^vsd chuck help? test marymary^);
print "\nTesting Words: @tests\n";
foreach (@tests) {
my ($word) = split /[!\^]/;
$word =~ s/[?\^]//g; # removes ^ and ?
if ( exists $common{ $word } ) {
print "Found: $word\n";
}
else {
print "Cannot find: $word\n";
}
}
下面是另一个同时读取两个文件的解决方案(假设两个文件的行数相等):
首先,将可重用段打包到子例程中:
sub read_file {
open my $fh, "<", $_[0] or die "read_file($_[0]) error: $!";
# lexical handles auto-close when they fall out of scope
# and detailed error messages are good
my %file;
while (my $line = <$fh>) {
chomp $line; # remove newline
$line =~ s{[!^].*}{}; # remove everything starting from ! or ^
$file{$line}++;
}
\%file
}
将打印:
common: yes
common: oh no
common: hello
common: help?
首先,我们必须规范您的输入。下面的代码为每个路径创建一个哈希。对于给定文件中的每一行,删除从第一个
开始的所有内容
或^
字符并记录其存在
sub read_inputs {
my @result;
foreach my $path (@_) {
my $data = {};
open my $fh, "<", $path or die "$0: open $path: $!";
while (<$fh>) {
chomp;
s/[!^].*//; # don't put the caret first without escaping!
++$data->{$_};
}
push @result, $data;
}
wantarray ? @result : \@result;
}
把它绑在一起
my @input = read_inputs "FileA", "FileB";
my @common = common @input;
print "$_\n" for sort @common;
输出
hello
help?
oh no
yes
你好
帮忙?
哦,不
是的,您是否认为文件A中的每一行都应该与文件B中的对应行进行比较?文件A和文件B的行数相等吗?不。文件A和文件B可以有不同的行数,并且行的顺序不必相同。嗨。我刚开始学习Perl,不太理解“my($fileA,$fileB)=map{read_file$}your_file_names_here();”您能进一步解释吗?
map
对列表应用转换并返回转换后的列表。它与my$fileA=read_文件('fileA.txt')相同;my$fileB=read_文件('fileB.txt')
如果列表('filea.txt','fileb.txt')
是由您的文件名\u在这里返回的
占位符。
sub read_file {
open my $fh, "<", $_[0] or die "read_file($_[0]) error: $!";
# lexical handles auto-close when they fall out of scope
# and detailed error messages are good
my %file;
while (my $line = <$fh>) {
chomp $line; # remove newline
$line =~ s{[!^].*}{}; # remove everything starting from ! or ^
$file{$line}++;
}
\%file
}
my ($fileA, $fileB) = map {read_file $_} your_file_names_here();
my %common;
$$fileA{$_} and $common{$_}++ for keys %$fileB;
print "common: $_\n" for keys %common;
common: yes
common: oh no
common: hello
common: help?
sub your_file_names_here {\(<<'/A', <<'/B')}
hello!world
help?!3233
oh no^!!
yes!
/A
hello
help?
oh no
yes
/B
sub read_inputs {
my @result;
foreach my $path (@_) {
my $data = {};
open my $fh, "<", $path or die "$0: open $path: $!";
while (<$fh>) {
chomp;
s/[!^].*//; # don't put the caret first without escaping!
++$data->{$_};
}
push @result, $data;
}
wantarray ? @result : \@result;
}
sub common {
my %matches;
for (@_) {
++$matches{$_} for keys %$_;
}
my @result = grep $matches{$_} == @_, keys %matches;
wantarray ? @result : \@result;
}
my @input = read_inputs "FileA", "FileB";
my @common = common @input;
print "$_\n" for sort @common;
hello
help?
oh no
yes