Perl: неожиданное совпадение переменных при использовании оператора?: - PullRequest
4 голосов
/ 06 сентября 2011

Попытка освободить некоторые переменные в Perl, и следующий код прекрасно работает:

if ($year =~ /^(\d{4})$/) {
        $year = $1;
} else {
        &invalid("year");
}

В приведенном выше примере $ 1 содержит $ year, если он действителен. Однако при использовании оператора ?: $ 1 содержит «1», когда он действителен:

($year =~ /^(\d{4})$/) ? $year = $1 : &invalid("year");

Кто-нибудь видит, где я могу быть виноват? Я запутался, почему это происходит. Это происходит только на этой машине. Вернее, я успешно использовал? оператор для возврата правильных переменных совпадения за годы. Я еще не пробовал этот кусок кода на любой другой машине.

This is Perl, v5.8.8 built for x86_64-linux-thread-multi

Ответы [ 3 ]

6 голосов
/ 06 сентября 2011

Будьте осторожны с приоритетом здесь.

Контраст http://codepad.org/vEPnhWfH, который работает, как ожидалось, с http://codepad.org/nXVU5CA7, который не работает. Конечно, я немного подправил код, чтобы избежать вызова invalid, но я подозреваю, что это может быть причиной проблемы.

В обоих случаях, хотя $1 содержит «2011», так что, возможно, вам следует показать дополнительный код, как того требует mu в первом комментарии.

UPDATE

Я изменил примеры кодов для использования вызова на &invalid, и ошибка не отображается.

sub invalid {
    print("INVALID\n");
}

sub check_with_if {
    print("Trying with if-statement\n");
    my $year = shift;
    if ($year =~ /^(\d{4})$/) {
        $year = $1;
    } else {
        &invalid($year);
    }
    print("\$1 is $1 and \$year is $year"."\n");
}

sub check_with_conditional {
    print("Trying with conditional expression\n");
    my $year = shift;
    ($year =~ /^(\d{4})$/) ? $year = $1 : &invalid($year);
    print("\$1 is $1 and \$year is $year"."\n");
}

check_with_if("2011");
check_with_conditional("2011");

Выход

Trying with if-statement 
$1 is 2011 and $year is 2011
Trying with conditional expression
$1 is 2011 and $year is 2011

http://codepad.org/z22GMEcn

РЕДАКТИРОВАТЬ 2 Также работает на 5.12.3 на Mac.

Я согласен с Джонатаном, что вы, возможно, обнаружили ошибку в 5.8.8, которая была исправлена ​​с тех пор. Если вам невероятно любопытно, вы можете пройти через изменения в Perl, такие как:

5 голосов
/ 06 сентября 2011

Perl Best Practices Дэмиена Конвея объясняет некоторые подводные камни использования переменных соответствия $1 и так далее, одна из них:

  • , если регулярное выражение ничего не соответствует, $1 не становится undef, но сохраняет прежнее значение (которое, конечно, в большинстве случаев является undef)

Моя интуиция говорит мне, что у вас есть проблема с контекстами - ваше выражение можетоценивать в скалярном контексте, возвращая, таким образом, количество совпадений, когда оно действительно.

Итак, я бы попробовал переписать код так:

($year) = ( $year =~ /^(\d{4})$/) or &invalid("year");
3 голосов
/ 06 сентября 2011

В Perl 5.14.1 (в MacOS X 10.7.1) этот скрипт работает нормально:

use strict;
use warnings;

my $year = "1984";

sub invalid
{
    my($year) = @_;
    print "Invalid year $year\n";
}

if ($year =~ /^(\d{4})$/)
{
    $year = $1;
}
else
{
    &invalid("year");
}


print "Year1: $year\n";

$year = "1984";
($year =~ /^(\d{4})$/) ? $year = $1 : &invalid("year");

print "Year2: $year\n";

Производит:

Year1: 1984
Year2: 1984

Если тот же скрипт выдает другой ответ в Perl 5.8.8, то, вероятно, вы столкнулись с ошибкой, которая была исправлена, и обновление в порядке. Если Perl 5.8.8 дает тот же ответ (как Perl 5.14.1), то вы еще не охарактеризовали свою проблему, чтобы я мог ее понять и воспроизвести проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...