Perl 字符串 if/or 比较运算符

Perl string if/or comparison operator

为什么是下面的代码:

# Get new_status
print STDERR "Please enter status value (active/inactive): ";
ReadMode(1);
my $new_status = ReadLine(0);
ReadMode(0);
print STDERR "\n";

if ( ($new_status ne "active") || ($new_status ne "inactive") )
{
  die "Status must be active/inactive.";
}

将始终 return "Status must be active/inactive." 无论我键入什么? (活动、非活动或其他任何内容,甚至只需按回车键即可。)

代码似乎有效:

关于 Perl 运算符,我显然有些地方没有完全掌握。 我做错了什么?

谢谢!

$new_status 不能同时等于 activeinactive,所以条件总是为真。您可能需要 && 而不是 ||

选择对您来说更直观的选项:

# option 1
if ( ($new_status ne "active") && ($new_status ne "inactive") )
...
# option 2
unless ( ($new_status eq "active") || ($new_status eq "inactive") )
...
#option 3
my %VALID_STATUS = (
    'active' => 1,
    'inactive' => 1,
);
if (!$VALID_STATUS{$new_status})
...
if ( ($new_status ne "active") || ($new_status ne "inactive") )
{
  die "Status must be active/inactive.";
}

让我们来研究逻辑。

  1. 我随机输入一些东西(让我们使用 random)。 random 不是 "active" 也不是 "inactive",因此您的 if 子句变为 if (true or true) - 这是正确的。
  2. 我输入 active。第一次检查为假,第二次检查为真,所以你得到 if (false or true) - 这是真的。
  3. 我输入 inactive。第一次检查是真的,第二次检查是假的,所以你得到 if (true or false) - 这是真的。

没有任何内容可以使您的 if 陈述错误。

你的问题是你不想用 or 加入你的两个子句,你应该改用 and

(并从这位老程序员那里得到一个提示 - 使用 andor 而不是 &&|| 进行流量控制会更容易混淆。)

更新: 总而言之,你的代码中有太多的负面因素,你自己也很困惑。在您的回答中,您(默默地!)将 if 更改为 unless,从而使维护程序员更难遵循代码。

我会这样写:

my $valid = $new_status eq 'active' || $new_status eq 'inactive';
if (not $valid) {
   die "...";
}

或者像这样:

use List::Util 'any';

if (not any { $new_status eq $_ } qw[active inactive] ) {
  die "...";
}

所以我找到了问题的答案。

格式问题。

我补充了:

print Dumper $new_status;

在我的代码中,输出是:

$VAR1 = 'active
';

所以我加了一个:

chomp $new_status;

现在一切正常。

$VAR1 = 'active';

最终代码:

# Get new_status
print STDERR "Please enter status value (active/inactive): ";
ReadMode(1);
my $new_status = ReadLine(0);
ReadMode(0);
print STDERR "\n";

chomp $new_status;

unless ( ($new_status eq "active") || ($new_status eq "inactive") )
{
  die "Status must be active/inactive.";
}

您只想在 $new_status 不是 active 时显示错误消息 AND 如果 $new_status 不是 [=17] =], 所以

if ( $new_status ne "active" || $new_status ne "inactive" )

应该是

if ( $new_status ne "active" && $new_status ne "inactive" )

我们可以证明这一点。记住De Morgan's laws.

  • !( A || B ) 等同于 !A && !B.
  • !( A && B ) 等同于 !A || !B.

所以,

  • 有效输入如果$new_status eq 'active' || $new_status eq 'inactive'
  • 如果 !( $new_status eq 'active' || $new_status eq 'inactive' )
  • 输入无效
  • 如果 !( $new_status eq 'active' ) && !( $new_status eq 'inactive' )
  • 输入无效
  • 如果 $new_status ne 'active' && $new_status ne 'inactive'
  • 输入无效

您需要习惯于看到以下内容:

if ( $new_status ne "active" && $new_status ne "inactive" ) {
   die("Status must be active/inactive.\n");
}

但您可能更喜欢使用自信的编码风格。

$new_status eq "active" || $new_status eq "inactive"    # Thing that should be true.
   or die("Status must be active/inactive.\n");         # Or what to do when it isn't.