为什么 Perl “不匹配”运算符在这里不起作用?

pac*_*low 1 regex string perl conditional-statements

我有以下 Perl 代码:

my $athCombined = "$athSymbol $athExpiration $athStrike $athType";
if (($instrumentType eq "STOCK" && $cbSymbol ne $athSymbol) ||
    ($instrumentType eq "OPTION" && $cbSymbol !~ /^$athSymbol.*$athExpiration $athStrike $athType$/) ||
    ($instrumentType eq "FUTURESOPTION" && $cbSymbol !~ /^$athCombined$/)) {
    print "ERROR: Symbols on lines $cbLineNum and $athLineNum don't match.  ABORTING.\n";
    print "instrumentType    =$instrumentType\n";
    print "cbSymbol          =$cbSymbol\n";
    print "athCombined       =$athCombined\n";
    print "length cbSymbol   =" . length($cbSymbol) . "\n";
    print "length athCombined=" . length($athCombined) . "\n";
    if ($instrumentType eq "FUTURESOPTION") {
        print "YES1\n";
    }
    if ($cbSymbol !~ /^$athCombined$/) {
        print "YES2\n";
    }
    if ($cbSymbol eq $athCombined) {
        print "they are the same\n";
    }
    exit;
}
Run Code Online (Sandbox Code Playgroud)

我得到以下输出:

ERROR: Symbols on lines 434 and 1906 don't match.  ABORTING.
instrumentType    =FUTURESOPTION
cbSymbol          =/ESM19 1/50 JUN 19 (Monday) (Wk1) /E1AM19 2745 CALL
athCombined       =/ESM19 1/50 JUN 19 (Monday) (Wk1) /E1AM19 2745 CALL
length cbSymbol   =51
length athCombined=51
YES1
YES2
they are the same
Run Code Online (Sandbox Code Playgroud)

该条件$cbSymbol !~ /^$athCombined$/将返回真实的,即使$cbSymbol$athCombined是相同的。如果我将条件更改为cbSymbol ne $athCombined,则它可以正常工作,但我想知道为什么它不能按原样工作。

有趣的是,我无法在一个简单的测试程序中重现这一点:

my $a = "1";
my $b = "2";
my $c = "3";
my $abc = "1 2 3";
my $def = "$a $b $c";
if ($abc !~ /^$def$/) {
    print "something is wrong\n";
}
Run Code Online (Sandbox Code Playgroud)

“出现问题”不会被打印出来。

Gri*_*nnz 9

$foo !~ /^$bar$/不等同于检查字符串不等式,如$foo ne $bar. 它检查是否$foo与 regex 不匹配^$bar$,这在$bar包含 regex 元字符时尤其不同,而且还$可以在(允许)尾随换行符之前匹配,而不仅仅是在字符串的末尾。(\z相当于$不允许尾随换行符。)

$athCombined在您的程序中 is /ESM19 1/50 JUN 19 (Monday) (Wk1) /E1AM19 2745 CALL,它包含正则表达式元字符()(在这种情况下它们形成捕获组,因此其他字符串中的文字括号与任何内容都不匹配)。您可以通过使用quotemeta 修饰符来解决这个问题:

$cbSymbol !~ /^\Q$athCombined\E\z/
Run Code Online (Sandbox Code Playgroud)

但更好的是使用字符串相等运算符,eq或者ne如果这就是您要测试的内容。