Perl — использование следующих внутренних подпрограмм — метка не найдена

У меня есть проблема, я надеюсь, что кто-то может пролить свет на...

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

Пример моей проблемы (значительно упрощенный для пояснения):

use warnings;
use strict;

sub mainprogram {

    my @foldernames = ("hugefolder", "smallfolder", "giganticfolder");

    SKIP:foreach my $folderName (@foldernames) {
             eval {    
                 $SIG{INT} = sub { interrupt() };     #to catch control-C keyboard command
                 my $results = `grep -R hello $folderName`;  #this takes a long time to grep if its a big folder so pressing control-c will allow the user to skip to the next folder/iteration of the foreach loop
             } 

             print "RESULTS: $results\n";

    }

}

sub interrupt {

     print "You pressed control-c, do you want to Quit or Skip this huge folder and go onto greping the next folder?\n";
     chomp ($quitOrSkip = <STDIN>);
     if ($quitOrSkip =~ /quit/) {
         print "You chose to quit\n";
         exit(0);
     } elsif ($quitOrSkip =~ /skip/) {
         print "You chose to skip this folder and go onto the next folder\n";
         next SKIP;   # <-- this is what causes the problem
     }  else {
         print "Bad answer\n";
         exit(0);
     }

} 

Проблема, с которой я столкнулся

Как вы можете видеть в приведенном выше коде, если пользователь нажимает ctrl+c во время выполнения команды grep с обратными кавычками для папки, это дает ему возможность выйти из программы. полностью или выберите переход к следующей папке в цикле массивов и начните ее поиск.

Однако с приведенным выше кодом вы неизбежно получите ошибку «Ярлык не найден для следующего ПРОПУСКА… в строке…», потому что он, очевидно, не может найти метку ПРОПУСТИТЬ, как в другой подпрограмме.

Есть ли способ сделать это или что-то с тем же эффектом, например, перейти к следующей итерации цикла foreach, даже если метка «следующий ПРОПУСК» и «ПРОПУСТИТЬ: foreach» находятся в разных подпрограммах.

Я хорошо знаю, что могу объединить две подпрограммы, чтобы «следующий ПРОПУСТИТЬ» находился в том же блоке, что и «ПРОПУСТИТЬ: foreach», чтобы он работал, но если программа вызывает подпрограмму «прерывание» много раз и во многих мест, то это будет означать много повторяющегося кода.

Я вполне могу упустить что-то очень очевидное, но ваша помощь очень ценится, спасибо


person yonetpkbji    schedule 07.08.2013    source источник


Ответы (1)


Вы можете переместить результаты печати внутрь eval, а затем die, если не хотите их печатать.

foreach my $folderName (@foldernames) {
    eval {    
        local $SIG{INT} = sub { interrupt() };     #to catch control-C keyboard command
        my $results = `grep -R hello $folderName`;  #this takes a long time to grep if its a big folder so pressing control-c will allow the user to skip to the next folder/iteration of the foreach loop
        print "RESULTS: $results\n";
        1;
    } or do {
        # handle the skip if required
    };
}

sub interrupt {
    ...
    die 'skip';
    ...
}

В качестве альтернативы:

foreach my $folderName (@foldernames) {
    eval {    
        local $SIG{INT} = sub { interrupt() };     #to catch control-C keyboard command
        my $results = `grep -R hello $folderName`;  #this takes a long time to grep if its a big folder so pressing control-c will allow the user to skip to the next folder/iteration of the foreach loop
        1;
    } or do {
        next; # Interrupted (or something went wrong), don't print the result.
    };
    print "RESULTS: $results\n";
}

sub interrupt {
    ...
    die 'skip';
    ...
}
person RobEarl    schedule 07.08.2013
comment
Я думаю, что это хорошо работает в простом примере в моем вопросе, но в чем-то более сложном, чем печать, я не думаю, что это действительно будет жизнеспособным вариантом? - person yonetpkbji; 07.08.2013
comment
Почему нет? Все, что в eval не было достигнуто, когда пользователь нажимает ctrl+c, будет пропущено. - person RobEarl; 07.08.2013