如果子字符串以一组字符串中的一个开头,我需要检查大文件每行的特定子字符串。由于我还需要每个可能密钥的另一个属性,因此我目前在散列中表示搜索字符串和关联值:
my %nops = ( # Name and length of needed headers
'POS1' => 308,
'POS2' => 305,
'POSSBNOP' => 309,
'PERFORAT' => 10,
'DOCVV' => 305,
'SPOOLING' => 308,
'DOCADR' => 305,
'DOCFARBE' => 305,
'DOCMAIL' => 305,
);
搜索字符串的最大长度为8个字符,因此我从输入文件的每一行中提取子字符串。可能的子串的一些示例是我的测试数据:
my @nop = ( 'POS1 000', # matches 'POS1'
'ABCDEF00', # no match (this would be the vast majority of lines in a file)
'SPOOLING', # matches 'SPOOLING'
'POS2 Rec', # matches 'POS2'
);
我有一个可行的解决方案,它要求我迭代哈希的键以找到正确的条目(如果它存在):
for my $n (@nop) { #
while ( my ($key, $value) = each(%nops) ) {
if ( $n =~ /^$key/ ) {
print "NOP $key found, length $value\n";
last;
}
}
}
我对解决方案不满意,因为它意味着对文件中的大多数行运行while循环的所有迭代。
我找到了另一个部分解决方案here,我喜欢它的简洁性,但它只告诉我哪些行匹配,而不是匹配的键,我需要弄清楚哈希值:
my $nop_keys = qr/${\ join('|', map quotemeta, keys %nops) }/;
for my $n (@nop) { #
print "String matched: $n\n" if $n =~ $nop_keys;
}
有没有更好的方法来解决这个问题? This question看起来很相关,但处理相反的情况:字符串与键匹配,而不是相反。也许不同的数据结构在这里会更有效率?
附带条件:我在Perl 5.10.0上,并且只能安装SUSE Linux Enterprise Server 11 SP2附带的任何其他软件包(不提供CPAN)。
答案 0 :(得分:4)
你只需要捕捉匹配的内容。
my $pat = join '|', map quotemeta, keys %nops;
my $re = qr/$pat/;
for my $n (@nop) {
my ($key) = $n =~ /^($re)/
or next;
my $val = $nops{$key};
...
}
答案 1 :(得分:1)
您可以通过从每行的开头捕获最多8个非空格字符并使用简单的哈希查找来更有效地处理此问题。
#!/usr/bin/env perl
use strict;
use warnings;
my %nops = (
# Name and length of needed headers
'POS1' => 308,
'POS2' => 305,
'POSSBNOP' => 309,
'PERFORAT' => 10,
'DOCVV' => 305,
'SPOOLING' => 308,
'DOCADR' => 305,
'DOCFARBE' => 305,
'DOCMAIL' => 305,
);
while (my $line = <DATA>) {
my ($key) = ($line =~ /\A ( \S{1,8} ) /x);
next unless $key and exists( $nops{ $key } );
print "$key => $nops{ $key }\n";
}
__DATA__
POS1 000 # matches 'POS1'
ABCDEF00 # no match (this would be the vast majority of lines in a file)
SPOOLING # matches 'SPOOLING'
POS2 Rec # matches 'POS2'
输出:
POS1 => 308 SPOOLING => 308 POS2 => 305
答案 2 :(得分:0)
拆分查询并将其用作哈希中的查找:
run_once
这假设密钥与空格的其余部分分开。