在Perl中,相等的字符串并不相等。

3

请帮助我理解一个字符串相等的奇怪问题。

以下是我所说的代码:

my $test=undef;
foreach my $List (@o_descrL) {
  if (!($test)) {
    $test = defined($o_noreg)
      ? $descr_d eq $List
      : $descr_d =~ /$List/i;
      printf("$descr_d = $List\t\t==> $test\n");
   }
}

很遗憾,我没有写这个代码,但我必须理解它。 $List 总是 "SQL Server (C4)",$descr_d 根据实际数组中的项目而变化。以下是打印输出的部分内容:

Power = SQL Server (C4)         ==>
SQL Server (C4) = SQL Server (C4)               ==>
SNMP Service = SQL Server (C4)          ==>
Network Connections = SQL Server (C4)           ==>

如您所见,输出的第二行中的字符串是相等的。那么为什么$test不是真的呢?


编辑:我打印了更多的输出,并发现当$descr_d eq $List时,它是相等的,但不是$descr_d =~ $List。请问您能解释一下实际上是什么在将$test变量设置为什么吗?我不明白这里的defined() ? :是什么意思。


编辑2:对于字符串"SQL Server Agent",脚本运行得很好,只有在(C4)附加时才会出问题。相当奇怪,不是吗?

1
你没有提到 defined($o_noreg) 是否为真。 - TLP
1个回答

11
当字符串被插值为正则表达式时,它不是按字面意义进行匹配,而是解释为正则表达式。这对于构建复杂的正则表达式非常有用,例如:
my @animals = qw/ cat dog goldfish /;
my $animal_re = join "|", @animals;

say "The $thing is an animal" if $thing =~ /$animal_re/i;

在字符串$animal_re中,竖线|被视为正则表达式元字符。
其他的元字符包括(...),它是一个捕获组。这个组在你的$List中存在。也就是说,你的正则表达式实际上是在查找字符串SQL Server C4并在成功时捕获C4
要停用元字符,可以像这样引用它们:
/\Q$metachars\E/

在您的情况下:
$test = defined($o_noreg)
      ? $descr_d eq $List
      : $descr_d =~ /\Q$List/i;

作为旁注,Perl的默认假值是空字符串。如果您将其强制转换为数字,例如通过$test += 0,则输出可能更易读。打印括在引号中的字符串也可能有助于理解:
print qq("$descr_d" = "$List"\t==> $test\n);

关于您的编辑

条件运算符 在类C语言中很常见。它由三个部分组成:

COND ? EXPR_A : EXPR_B

如果条件COND为真,则计算表达式EXPR_A;否则,计算EXPR_B。在您的代码中,被计算的表达式的值被分配给$testdefined内置函数测试标量保存的值是否为undef。如果是这种情况,则返回false值,否则返回1。这用于某些配置:当$o_noreg被设置为任何值,而不是undef时,将使用默认字符串比较。如果它是undef,则执行正则表达式。
回复:编辑2
不,这并不奇怪:SQL Server(C4)包含元字符,而SQL Server Agent根本不包含元字符。

@TLP 可能有点挑剔,例如 /\Q$List//\Q$List\E/,但很难说清楚。 - mpapec
@mpapec 结束转义序列是可选的。 - TLP

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接