2009-05-23 28 views
7

Khi tôi in kết quả của regex tôi đang cố gắng sử dụng để kiểm soát vòng lặp cho đến khi nó mang lại cho tôi 1 hoặc null tôi mong đợi. Tại sao mã bên dưới không hoạt động nhưng nếu tôi bỏ ghi chú dòng thứ năm thì nó hoạt động tốt?Perl regex không vi phạm cho đến khi vòng lặp như mong đợi

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]/); 
} 

Tôi chắc chắn điều này đã được giải quyết ở nơi khác nhưng không thể tìm thấy bằng tìm kiếm. Chỉ cho tôi đi đúng hướng sẽ là tuyệt vời.

Tôi thường làm như thế.

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]/); 
} 

Nhưng tôi đang cố thoát khỏi các vòng vô hạn.

Trả lời

18

Vấn đề ở đây là bạn đang khai báo lại $ channelSelection trong vòng lặp nhưng bên ngoài vòng lặp giữ giá trị cũ. Loại bỏ "của tôi" từ vòng lặp bên trong.

11

Bạn đã redeclared $channelSelection cục bộ trong vòng lặp cho đến. Bằng cách đó, giá trị của nó sẽ bị mất mỗi khi vòng lặp thực hiện. Vì vậy, cụm từ thông dụng sẽ không khớp với giá trị sau đó của $channelSelection một lần nữa sẽ bằng "".

Xóa my khỏi vòng lặp sẽ giải quyết được sự cố.

+0

Heh, cùng một câu trả lời, cách nhau 6 lần. :) –

+0

Có tôi muốn cung cấp cho bạn kiểm tra nhưng Artem đã từng nhanh hơn một chút. hehe Good job tho +1 – Copas

+0

Thật tuyệt! :-) –

6

Bạn không lo lắng về điều đó?

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

Đây là giải pháp sạch hơn bằng mọi cách, miễn là OP có quyền truy cập để cài đặt các mô-đun - Thuật ngữ :: Menu không phải là một phần của vùng Perl tiêu chuẩn. Tuy nhiên, hỗ trợ tốt. –

+0

Giải pháp tuyệt vời không may mã này cần chạy trên HP-UX 10.2 chạy perl 5.004_04. Để làm cho vấn đề tồi tệ hơn là có khá nhiều không có cách nào để cập nhật bất kỳ điều này (nhiều ít cài đặt một mô-đun). Trong ngành công nghiệp tôi làm việc trong chúng tôi đang liên tục chiến đấu để có được bất kỳ nâng cấp cho bất cứ điều gì đó không phải là công nghệ của năm 1950. – Copas

+0

@Artem tốt, OQ đã được trả lời, vì vậy tôi muốn hiển thị một thay thế. BTW, http://perldoc.perl.org/perlfaq8.html#How-do-I-keep-my-own-module%2flibrary-directory%3f có thể hữu ích. –

3

Giải pháp tốt nhất để nhận dữ liệu nhập từ người dùng là sử dụng IO :: Mô-đun nhắc. Nó hỗ trợ lặp lại, xác nhận, hệ thống menu và nhiều hơn nữa.

+0

Có vẻ như các vấn đề về tính di động được chỉ ra bởi người đánh giá mô-đun - hãy cẩn thận với những người đó. –

2

Đây là vấn đề về phong cách (vì bạn không thể cài đặt mô-đun, nó không giúp bạn), nhưng tôi chỉ muốn chỉ ra rằng khi kiểm tra giá trị cố định, sử dụng regex có lẽ không phải là giải pháp tốt nhất.

Đây là là những gì tôi sẽ làm gì:

use List::MoreUtils; 

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

# get $answer from prompt. 

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

Có thể có ích trong một thời gian khác.

+0

Tôi đồng ý điều này dường như là một cách tốt hơn để làm điều đó (nếu chỉ). Có cách nào tốt hơn để làm điều đó trong tinh khiết perl 5.004? Cảm ơn +1 vì đã cho thấy một bản mod tuyệt vời. – Copas

+0

Tôi đoán bạn có thể nâng chức năng từ mô-đun và kiểm tra xem nó có hoạt động hay không. Nó chỉ là một vài dòng và dường như không làm bất kỳ phép thuật nào .. – Anon

Các vấn đề liên quan