ฉันจะแยกออกจากวงใน Perl ได้อย่างไร


295

ฉันพยายามที่จะใช้breakคำสั่งในforวง แต่เนื่องจากฉันยังใช้หมวดย่อยอย่างเข้มงวดในรหัส Perl ของฉันฉันได้รับข้อผิดพลาดว่า:

Bareword "break" ไม่ได้รับอนุญาตในขณะที่ใช้ "subs subs" อย่างเข้มงวดที่. /final.pl บรรทัดที่ 154

มีวิธีแก้ปัญหาสำหรับสิ่งนี้ (นอกเหนือจากการปิดใช้งานหมวดย่อยที่เข้มงวด)?

รหัสของฉันมีรูปแบบดังนี้:

for my $entry (@array){
    if ($string eq "text"){
         break;
    }
}

22
และหากคุณไม่ได้เปิด "subs subs" อย่างต่อเนื่องคุณจะได้รับข้อผิดพลาดรันไทม์แทนเมื่อไม่พบหัวข้อย่อย "break"
Paul Tomblin

คำตอบ:


441

โอ้ฉันพบแล้ว คุณใช้ครั้งสุดท้ายแทนที่จะหยุดพัก

for my $entry (@array){
    if ($string eq "text"){
         last;
    }
}

แม้ว่านี่จะเป็นเพียงความแตกต่างทางความหมายและไม่ได้เป็นอย่างอื่นนอกจากความสอดคล้องกับต้นฉบับด้วยคำสั่ง "ถัดไป"
มีดโกนพายุ

1
ไม่ต้องพูดถึงว่า 'break' เป็นคำหลักทดสอบใน> 5.010 ใช่ไหม ดังนั้นคุณอาจได้รับข้อผิดพลาดนอกบล็อกที่กำหนดไม่ใช่ว่าคุณควรใช้ วิธีเดียวที่จะใช้งานได้คือถ้าคุณใช้การวนรอบสักครู่ภายในบล็อกที่กำหนดและจากนั้นหยุดซึ่งในทางทฤษฎีจะทำงานในแบบที่คุณต้องการหาก IF (และเฉพาะในกรณี) บล็อกที่ให้นั้นมีห่วงในขณะนั้นอยู่แล้ว สมมติว่าคุณเพิ่งป้อนอาหารให้กับตัวแปรสเกลาร์บางส่วน ... แต่ทำไมทั้งหมดที่ใช้เพื่อหยุดพักมันเป็นรูปแบบที่แย่มาก (มาก) ไม่พูดถึง (blah!) เพียงแค่พูดว่า "เป็นไปได้" ไม่ดี คิดและไม่ใช่สิ่งที่คุณอาจคิดว่าเป็น
osirisgothra

25
ด้วยเหตุผลบางอย่างฉันไม่สามารถจดจำคำหลักนี้ได้ 'สมบูรณ์' มักจะจบลงด้วย googling 'perl break loop' :(
Thupten

นอกจากนี้ยังทำงานเหมือนกันสำหรับwhile() ลูป my @array = ("_", "apple", "orange"); my $thing; while ($thing = shift @array){ last if $thing =~ /[A-Za-z]/; } print($thing); # "apple"
HoldOffHunger

175

ข้อมูลเพิ่มเติม (ในกรณีที่คุณมีคำถามเพิ่มเติม):

FOO: {
       for my $i ( @listone ){
          for my $j ( @listtwo ){
                 if ( cond( $i,$j ) ){

                    last FOO;  # --->
                                   # |
                 }                 # |
          }                        # |
       }                           # |
 } # <-------------------------------

2
คุณไม่จำเป็นต้องใช้เครื่องมือจัดฟันหลัง FOO:
cjm

14
คุณจะทำอย่างไรถ้าคุณมีรหัสอื่นหลังจากที่วน $ i ของฉันที่คุณต้องการข้าม {} ด้านนอกเป็นบล็อกเปลือยซึ่งเป็นวงตลกที่สามารถอยู่ / redo / next'd ได้
ysth

18

lastจะทำงานที่นี่เพียง:

for my $entry (@array){
    if ($string eq "text"){
         last;
    }
}

หากคุณมีลูปซ้อนกันแล้วlastจะออกจากวงในสุด ใช้ป้ายกำกับในกรณีนี้:

LBL_SCORE: {
    for my $entry1 (@array1) {
        for my $entry2 (@array2) {
            if ($entry1 eq $entry2) { # Or any condition
                last LBL_SCORE;
            }
        }
    }
 }

ให้lastคำสั่งจะทำให้คอมไพเลอร์ที่จะออกมาจากลูปทั้งสอง สามารถทำได้เช่นเดียวกันในลูปจำนวนเท่าใดก็ได้และสามารถแก้ไขป้ายกำกับได้ทุกที่


6

ในการทำซ้ำครั้งใหญ่ฉันชอบใช้การขัดจังหวะ เพียงกดCtrl+ Cเพื่อออก:

my $exitflag = 0;
$SIG{INT} = sub { $exitflag=1 };

while(!$exitflag) {
    # Do your stuff
}

คำแนะนำที่มีประโยชน์มากแน่นอน +1
Keve

@PeterMortensen - สิ่งนี้ทำงานได้ดีใน windows สิ่งเดียวที่ต้องจำไว้สำหรับ windows คือการเปิด autoflush ถ้าคุณพิมพ์ไปยัง STDOUT '$ | = 1;'
MortenB
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.