空$1和$2值Regex Perl

空$1和$2值Regex Perl,regex,perl,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_p

我有以下代码:

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.

当您无法匹配时,您希望
$1
$2
包含什么内容

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

可能的解决办法:

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

$sDatabase=~s/(?此代码将执行您想要的操作

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";
}
你有:

my $sDatabase = "abc_def:xyz_comp.";
if ($sDatabase =~ m/^(\w)*\:(\w*)\_em\.$/);
让我们看看这是否匹配:

你的正则表达式说:

  • 锚定在一条线的起点
  • 您正在查找零个或多个单词字符。单词字符(ASCII字母表中)包括小写字母、大写字母、数字和下划线。
    • 因此,
      /\w*/
      将匹配以下所有内容:
    • 计算机
    • 计算机
    • 计算机23
    • 计算机32
    • 空字符串
  • 你接下来要找的是冒号
  • 然后,更多的单词字符
  • 后跟一个
    \u em
    字符串
  • 然后是一段时间
  • 这应该是字符串的结尾(如果没有NL,并且您没有进行多行字符串搜索,看起来您在那里很安全)
现在,让我们看看您的字符串:
abc_def:xyz_comp.

  • \w*
    将匹配到
    abc_def
    。正则表达式是贪婪的,将尝试匹配字符串的最大部分
  • 将匹配冒号。到目前为止,您正在匹配
    abc\u def:
  • \w*
    将在
    xyz\u comp
    上匹配
  • 现在,您正在尝试匹配
    \u em
    .Oops!不好。字符串中没有
    \u em
    。正则表达式匹配将失败
由于正则表达式匹配失败,
$1
$2
变量未设置且没有值

这就是为什么要使用未初始化值的原因。您可以做的是将表达式的后半部分设置为可选:

}

首先,我认为您希望至少匹配一个字符(我可能错了),因此我将匹配零个或多个字符的星号切换为匹配一个或多个字符的
+

注:我有第三组括号,后面跟一个
。这意味着将这个匹配0次或1次。因此,您将有一个匹配,
$1
$2
将被设置,只要您的字符串以一个或多个单词字符开头,后跟一个冒号,后跟一个或多个单词字符

不一定会设置
$3
。仅当字符串也以
\u em.
结尾时才会设置。如果字符串不包括
\u 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是
\u em.
要么我们将
\u em.
添加到匹配项的末尾。

$1应该有abc\u def$2应该有xyz\u comp这是怎么可能的?模式不匹配。但我仍然希望在其他条件下得到结果。如果我是一个,对不起我说不通。这怎么可能?你没有在听。这是不可能的。
if(/…/){…}else{…}
中的匹配在执行到else分支时不会设置
$1
,因为你从未告诉它在
$1
中放置什么。你不能使用该模式。好的,谢谢。那么如何分配“abc_def:xyz_comp”如果$sDatabase的值为“abc_def:xyz_comp_em.”并将其赋值为“abc_def:xyz_comp_em.”如果$sDatabase等于“abc_def:xyz_comp.”如果$sDatabase=“abc_def:xyz_comp_em.”那么我想要$sDatabase=“abc_def:xyz_comp_comp.”请帮助。啊,我明白了。好的,我已经解决了。如何无条件地
打印“$1:$2$3.\n”
在幸存下来后,m//?
(\w+?)
是有效的正则表达式吗?我想你想要
(\w+)
@David w.,不,他写的是正确的。(尽管如此,我鄙视非贪婪修饰符。非常脆弱。你不能在同一模式中使用它两次。)
(?:\u em)?
将始终与空字符串匹配。如果存在,您将加倍
\u em
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);
}