Regex Perl正则表达式未按预期中断直到循环

Regex Perl正则表达式未按预期中断直到循环,regex,perl,Regex,Perl,当我打印正则表达式的结果时,我试图用它来控制until循环,它给出了我期望的1或null。为什么下面的代码不起作用,但如果我取消第五行的注释,它就可以正常工作 print("Please enter 1, 2, 3 or 4 : "); my $channelSelection = ""; until ($channelSelection =~ /^[1-4]$/) { chomp(my $channelSelection = <STDIN>); #last if

当我打印正则表达式的结果时,我试图用它来控制until循环,它给出了我期望的1或null。为什么下面的代码不起作用,但如果我取消第五行的注释,它就可以正常工作

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]/);
}
打印(“请输入1、2、3或4:”;
我的$channelSelection=“”;
直到($channelSelection=~/^[1-4]$/){
chomp(我的$channelSelection=);
#最后一个if($channelSelection=~/^[1-4]$/);
打印(“无效选择($channelSelection)请重试:)
如果($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]/);
}
打印(“请输入1、2、3或4:”;
我的$channelSelection=“”;
而(1){
chomp(我的$channelSelection=);
最后一个if($channelSelection=~/^[1-4]$/);
打印(“无效选择($channelSelection)请重试:”)如果($channelSelection!~/[1-4]/);
}

但我正试图摆脱无限循环。

您已经在until循环中本地重新声明了
$channelSelection
。这样,每次循环执行时,其值都将丢失。因此,正则表达式将不匹配,因为
$channelSelection
的值将再次等于
“”


从循环中删除
my
将解决此问题。

这里的问题是您在循环中声明$channelSelection,但循环外部保留旧值。将“我的”从内部循环中删除。

不用担心它怎么样

#!/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__

获取用户输入的最佳解决方案是使用IO::Prompt模块。它支持重复、验证、菜单系统和更多功能。

这更多是一个风格问题(因为您无法安装模块,所以它对您没有帮助),但我只想指出,在检查固定值时,使用正则表达式可能不是最好的解决方案

这就是我要做的:

use List::MoreUtils;

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

# get $answer from prompt.

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

可能在其他时间派上用场。

Heh,同样的答案,相隔6秒。:)是的,我想给你支票,但阿泰姆的速度比我快了一点。hehe Good job tho+1这是一个更干净的解决方案,只要OP有权安装模块-Term::Menu不是标准Perl dist的一部分。但是,很好的帮助。很遗憾,此代码需要在运行Perl 5.004_04的HP-UX 10.2上运行。更糟糕的是,几乎没有办法更新这些内容(更不用说安装模块了)。在我工作的行业中,我们一直在为任何非1950年代技术的升级而奋斗。@Artem好吧,OQ已经得到了回答,所以我想展示一个替代方案。顺便说一句,也许会有用。@Copas我对你的感觉。啊@Artem Russakovskii,请不要向人们介绍这个想法,他们通常可以安装模块,你不应该吓唬他们,让他们认为他们无法安装,而他们已经倾向于假设,这是一种罕见的情况,当你实际上无法安装时。模块评审员似乎指出了一些可移植性问题——要小心这些问题。我同意这似乎是一种更好的方法(如果有的话)。在纯perl 5.004中有更好的方法吗?感谢+1显示了一个很酷的mod。我想你可以从模块中取出该功能并检查它是否工作。这只是几句话,似乎没有任何魔力。。