2013-04-29 24 views
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

该代码会做你想要

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"; 
} 
+0

。那么我想要$ sDatabase =“abc_def:xyz_comp”。 请帮忙。 – 2013-04-29 19:32:20

+0

啊我明白了。好的,我修好了。 – Borodin 2013-04-29 19:47:16

+0

如何无条件地“打印”$ 1:$ 2 $ 3。\ n“'幸存了m //之后? – pilcrow 2013-04-29 20:44:55

3

你有什么期望$1$2含有当你不匹配?

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

可能的解决方案:

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

$ 1应该有abc_def $ 2应该有xyz_comp – 2013-04-29 19:12:53

+0

这怎么可能?模式不匹配。 – ikegami 2013-04-29 19:13:06

+0

但我仍然想在其他条件的结果。对不起,如果我没有意义。这怎么可能? – 2013-04-29 19:16:38

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

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

+0

感谢您的详细回复! =) – 2013-04-29 21:54:25

+0

'(?:_ em)?'将始终与空字符串匹配。如果它存在,你最终会将_em加倍。 – ikegami 2013-04-29 22:31:48