你有:
my $sDatabase = "abc_def:xyz_comp.";
if ($sDatabase =~ m/^(\w)*\:(\w*)\_em\.$/);
让我们看看这是否匹配:
你是正则表达式说:
- 锚定在一行的开头。
- 您正在寻找零个或多个单词字符。单词字符(在 ASCII 字母表中)包括小写字母、大写字母数字和下划线。
- 因此
/\w*/
将匹配以下所有内容:
- 计算机
- 计算机
- 电脑23
- 电脑_32
- 一个空字符串
- 你接下来要找一个冒号
- 然后,更多的单词字符
- 后跟一个
_em
字符串
- 后面跟着一个句号
- 那应该是字符串的结尾(如果没有 NL 并且您没有进行多行字符串搜索。看起来您在那里很安全)。
现在,让我们看看你的字符串:abc_def:xyz_comp.
\w*
将匹配到abc_def
。正则表达式是贪婪的,会尽量匹配字符串的最大部分。
- 将
:
匹配冒号。到目前为止,您正在匹配abc_def:
.
- 那
\w*
将匹配xyz_comp
.
- 现在,您正在尝试匹配一个
_em
. 哎呀!不好。你的字符串中没有_em
。您的正则表达式匹配将失败。
由于您的正则表达式匹配失败,$1
and$2
变量根本没有设置并且没有任何值。
这就是为什么你得到Use of uninitialized value
. 您可以做的是使表达式的后半部分变为可选:
my $sDatabase = "abc_def:xyz_comp.";
if ($sDatabase =~ /^(\w)+:(\w*)(_em)?\.$/) {
if ( $3 ) {
print "$1:${2}${3}.\n";
else {
print "$1:${2}_em.";
}
}
else {
die qq(String doesn't match regular expression at all\n);
}
}
首先,我认为你想匹配至少一个字符(我可能是错的),所以我将匹配零个或多个的星号切换为+
匹配一个或多个的星号。
请注意,我有第三组括号,后跟一个?
. 这意味着匹配这个零次或一次。因此,您将有一个匹配项,并且$1
只要$2
您的字符串以一个或多个单词字符开头,后跟一个冒号,然后是一个或多个单词字符,就会被设置。
不一定会发生的事情$3
将被设定。仅当您的字符串也以 . 结尾时才会设置_em.
。如果您的字符串不包含_em
, 但以句点结尾,$1
并且$2
仍然匹配。
在您的情况下,我们可以通过这样做来简化它:
my $sDatabase = "abc_def:xyz_comp.";
if ($sDatabase =~ /^(\w)+:(\w*)(?:_em)?\.$/) {
print "$1:${2}_em.";
else {
die qq(String doesn't match regular expression at all\n);
}
(?:...)
手段不设置匹配,只是分组。因此,$3
永远不会被设置。没关系,要么是 3 美元,要么_em.
我们无论如何都会添加_em.
到比赛的结尾。