2

我有以下代码:

my $sDatabase = "abc_def:xyz_comp.";
if ($sDatabase =~ m/^(\w)*\:(\w*)\_em\.$/)
{
    print "$1\:$2\.\n";
}
else
{
    print "$1\:$2\_em\.\n";
}

但我越来越空$1$2。输出是:

Use of uninitialized value in concatenation (.) or string at new_mscn_iden_parse.pl line 187.
Use of uninitialized value in concatenation (.) or string at new_mscn_iden_parse.pl line 187.
:_em.
4

3 回答 3

4

这段代码会做你想做的

my $sDatabase = "abc_def:xyz_comp.";

$sDatabase =~ m/^(\w+):(\w+?)(_em)?\.$/ or die "Invalid data";
if ($3) {
  print "$1:$2.\n";
}
else {
  print "$1:$2_em.\n";
}
于 2013-04-29T19:26:34.650 回答
3

当您无法匹配时,您期望$1并包含什么?!$2

它包含您尝试匹配之前包含的任何内容。

可能的解决方案:

$sDatabase =~ s/(?<!_em)(?=\.\z)/_em/;
于 2013-04-29T19:11:52.047 回答
1

你有:

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。您的正则表达式匹配将失败。

由于您的正则表达式匹配失败,$1and$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.到比赛的结尾。

于 2013-04-29T21:32:32.817 回答