Perl регулярное выражение не прерывается до цикла, как ожидалось - PullRequest
7 голосов
/ 23 мая 2009

Когда я печатаю результат регулярного выражения, который я пытаюсь использовать для контроля цикла, он дает мне 1 или ноль, который я ожидаю. Почему код ниже не будет работать, но если я раскомментирую пятую строку, она будет работать нормально?

print("Please enter 1, 2, 3 or 4 : ");
my $channelSelection = "";

until ($channelSelection =~ /^[1-4]$/) {
    chomp(my $channelSelection = <STDIN>);
    #last if ($channelSelection =~ /^[1-4]$/);
    print ("Invalid choice ($channelSelection) please try again: ") 
        if ($channelSelection !~ /[1-4]/);
}

Я уверен, что это было решено в другом месте, но не смог найти его с помощью поиска. Было бы замечательно указать мне правильное направление.

Я бы обычно делал что-то вроде.

print("Please enter 1, 2, 3 or 4 : ");
my $channelSelection = "";
while (1) {
    chomp(my $channelSelection = <STDIN>);
    last if ($channelSelection =~ /^[1-4]$/);
    print ("Invalid choice ($channelSelection) please try again: ") if ($channelSelection !~ /[1-4]/);
}

Но я пытаюсь уйти от бесконечных петель.

Ответы [ 5 ]

18 голосов
/ 23 мая 2009

Проблема в том, что вы повторно объявляете $ channelSelection внутри цикла, но за пределами цикла сохраняется старое значение. Удалите «мое» из внутренней петли.

11 голосов
/ 23 мая 2009

Вы повторно объявили $channelSelection локально в цикле до. Таким образом, его значение будет потеряно при каждом выполнении цикла. Поэтому регулярное выражение не будет совпадать, так как тогда значение $channelSelection снова будет равно "".

Удаление my из цикла устранит проблему.

6 голосов
/ 24 мая 2009

Как насчет того, чтобы не беспокоиться об этом?

#!/usr/bin/perl

use strict;
use warnings;

use Term::Menu;

my @channels = qw( 1 2 3 4 );

my $prompt = Term::Menu->new(
    aftertext => 'Please select one of the channels listed above: ',
    beforetext => 'Channel selection:',
    nooptiontext =>
        "\nYou did not select a valid channel. Please try again.\n",
    toomanytries =>
        "\nYou did not specify a valid channel, going with the default.\n",
    tries => 3,
);

my $answer = $prompt->menu(
    map { $_ => [ "Channel $_" => $_ ] } @channels
);

$answer //= $channels[0];

print "$answer\n";

__END__
3 голосов
/ 24 мая 2009

Лучшее решение для получения ввода от пользователя - использовать модуль IO :: Prompt. Он поддерживает повторы, проверки, систему меню и многое другое.

2 голосов
/ 24 мая 2009

Это скорее проблема стиля (и поскольку вы не можете установить модули, это вам не поможет), но я просто хотел отметить, что при проверке фиксированных значений использование регулярных выражений, вероятно, не является лучшим решение.

Вот что я бы сделал:

use List::MoreUtils;

my @allowed_values = qw( 1 2 3 4 );

# get $answer from prompt.

if(any { $_ == $answer } @allowed_values) {
    # All is good.
}

Может пригодиться в другой раз.

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