清空$ 1和$ 2值Regex Perl

时间:2013-04-29 19:07:33

标签: regex perl

我有以下代码:

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.

3 个答案:

答案 0 :(得分: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";
}

答案 1 :(得分:3)

当您未能匹配时,您希望$1$2包含哪些内容?!

它包含尝试匹配前包含的内容。

可能的解决方案:

$sDatabase =~ s/(?<!_em)(?=\.\z)/_em/;

答案 2 :(得分:1)

你有:

my $sDatabase = "abc_def:xyz_comp.";
if ($sDatabase =~ m/^(\w)*\:(\w*)\_em\.$/);

让我们看看这是否匹配:

你是正常的表达说:

  • 在一条线的起点处锚定。
  • 您正在寻找 或更多字符。单词字符(ASCII字母表)包括小写字母,大写字母 数字 下划线
    • 因此/\w*/将匹配以下所有内容:
    • 计算机
    • 计算机
    • computer23
    • computer_32
    • 一个空字符串
  • 你接下来正在寻找一个冒号
  • 然后,更多的单词字符
  • 后跟_em字符串
  • 接下来的一段时间
  • 这应该是字符串的结尾(如果没有NL而你没有进行多行字符串搜索。看起来你在那里很安全。)

现在,让我们看一下你的字符串:abc_def:xyz_comp.

  • \w*将匹配abc_def。正则表达式是贪婪的,并且会尽可能地匹配字符串的最大部分。
  • :将匹配冒号。到目前为止,您正在匹配abc_def:
  • \w*将匹配xyz_comp
  • 现在,您正在尝试匹配_em。哎呀!不好。您的字符串中没有_em。您的正则表达式匹配将失败。

由于正则表达式匹配失败,$1$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。< / p>

不一定会发生$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.