Perl正则表达式捕获字符串中的精确匹配并存入变量

3

我需要帮助编写一个正则表达式,只捕获字符串中的精确匹配,并将其放入变量中。

我只想提取这些值(固定列表;没有其他数字):

004010H222A1 or 
004010H223A2 or 
004010H220A1 or 
004010H279A1 or 
004010H279A1 or 
004010H217 

从给定的字符串中提取

示例:

$str = "this is the code 004010H222A1 the rest is irrelevant";
$str = "the random number is 004010H223A2 ** anything else is irrelevant";
$str = "the last lottery number 004010H220A1 ~~ the rest is irrelevant";
$str = "yet another random sentence 004010H279A1 the rest is irrelevant";
$str = "any sentence before what i want 004010H279A1 the rest is irrelevant";
$str = "last winning number 004010H217~~~";


if ($str =~ /\b(004010H[2][1|2|7][0|2|3|7|9])(A[1|2])?\b/){
print "found exact match\n";
##put result into a variable
##example:
## $exact_match = <found eg 004010H222A1>; 
##print $exact_match;
}

我该如何将我想要的精确匹配内容存储到一个变量中并显示出来?也许我只是看不到眼前的森林。非常感谢您的帮助。


^.*(004010H[0-9A]{0,10}) - Uncle Iroh
或者仅将其设置为:^.*(004010H222A1|004010H223A2|004010H220A1|004010H279A1|004010H279A1|004010H217) - Uncle Iroh
2个回答

1
给定一组模式列表。
my @fixed = qw(004010H222A1 004010H223A2 004010H220A1 
    004010H279A1 004010H279A1 004010H217);

my $str = "this is the code 004010H222A1 the rest is irrelevant";

my @found = grep { $str =~ /$_/ } @fixed;

这个模式在字符串中匹配所有这样的模式。请注意,您可能需要单词边界(/\b$_\b/),尽管不需要如果模式在周围文本中非常明显。如果模式本身包含任何非单词字符,则需要为“边界”构建子模式。

如果您确定字符串中只有一个或只需要第一个

my ($found) = grep { $str =~ /$_/ } @fixed;

或者先使用交替构建模式。
my $re = join '|', map { quotemeta } @fixed;

my $found = $str =~ /$re/;  # consider using word-boudaries /\b$re\b/

这种方法可能更有效,因为它只启动一次正则表达式引擎,但另一方面,如果只有几个(或一个?)选项,我们会涉及所有开销来形成替代。

根据细节,您可能希望首先按长度排序,无论是最长还是最短。

my $re = join '|', map { quotemeta } sort { length $a <=> lenght $b } @fixed;
...

请参阅此帖子以了解有关这些选项背后的推理讨论。


如果您有更多可能性,并且与问题中显示的确切模式匹配,则该模式为:数字后跟字母或数字,以非字母数字终止。
my $pattern = qr/([0-9]+[a-zA-Z0-9]+)[^a-zA-Z0-9]/;

my ($found) = $str =~ /$pattern/;

如果模式紧接在非数字字符(如~)之后,而不仅仅是空格,则上述匹配成功。它还允许小写字母,如果不能使用,则删除a-z。如果确定存在前导零,则可以进一步限制此内容。

谢谢你的想法,我一直在测试并且很喜欢。再次感谢! - user2585000
@user2585000 欢迎,很高兴你喜欢它 :) 当你有一个固定模式的列表时,这是一个不错的小“技巧”。 - zdim

1
只是想发表一下我的意见:
\b004010H2[127][02379](?:A[12])?\b
# \b - match a word boundary
# match 004010H2 literally
# [127] one of 1,2 or 7
# followed by one of 0,2,3,7 or 9
# (?:....)? is a non capturing group and optional in this case

提示:显然,这可以匹配您的数字,但其他组合如004010H210A2也可以。这完全取决于您的输入字符串。如果您只有这六种选择,那么使用简单的字符串函数可能会更安全。
请参见regex101.com上的演示


谢谢,那个演示网站帮助我调试了一些提出的想法。同时也感谢指出可选部分捕获组。 - user2585000

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接