2013-07-29 2 views
4

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

У меня есть цикл по каждому элементу, который выполняет обратные кавычки команду на каждая итерация, например, сглаживание папки в каталоге для строки (как показано ниже, значительно упрощается для объяснения моего вопроса).

my @folderList = ("/home/bigfolder", "/home/hugefolder", "/home/massivefolder"); 
my @wordList = ("hello", "goodbye", "dog", "cat"); 

foreach my $folder (@folderList) { 
    foreach my $word (@wordList) { 
      print "Searching for this $word in this $folder\n"; 
      my @output = `grep -R $word $folder`; #this could take hours so the user needs the option to skip/cancel this iteration and go the next one 
      print "@output\n"; 
    } 
} 

Проблема, которую я имею:

Если папка кавычка Grep команда в настоящее время работают с особенно большой или массивом слов, чтобы проверить против особенно велико, то команда обратных кавычек может занять часов для завершения (что хорошо).

Но я хочу, чтобы иметь возможность сделать это, чтобы вырваться из внутреннего цикла (т.е. когда слово скопилось в папке) и перейти к следующей итерации, если это занимает много времени, когда пользователь нажимает клавишу на клавиатуре или, например, вводит слово «следующий» или «выход».

Я знаю, что если я не был с помощью кавычки я мог легко выйти из нормального цикла, используя что-то вроде следующего (но логика это, очевидно, не работает, когда обратные кавычки/системный вызов участвует):

use strict; 
use warnings; 

use Term::ReadKey; 

my $n = 0; 

while() { 
    print '.'; 
    last if ReadKey(-1); 
    $n++; 
} 

print $n; 

Там может быть простым решение, которое я с видом, но я никогда не имел необходимости сделать это раньше, поэтому ваша помощь очень ценится, благодаря

ответ

0

Я понимаю, что люди говорят о фоновых процессах, потоки и разветвление и так далее, , но тот вариант, который подходит моему расположению лучших (и, вероятно, это проще реализовать), хотя я признаюсь, что это не самая эффективная, лучшая практика или предпочтительный способ ее выполнения, связанный с использованием eval и catching control-c-control.

Очень простой пример:

NEXT:foreach $folder (@folders) {  #label on the foreach 

     eval { 
       $SIG{INT} = sub { break() }; #catches control-c keypress and calls the break subroutine 
       $var1 = `grep -r "hello" $folder`; 
     }; 

     sub break { 
       print "Breaking out of the backticks command and going to next folder \n"; 
       next NEXT; 
     } 

    } #ending bracket of foreach loop 
2

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

Все части, о которых я упоминал, хорошо объяснены в предыдущих сообщениях о переполнении стека.

1

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

Вот схема того, как вы могли бы использовать вилку:

use POSIX ':sys_wait_h'; # defines WNOHANG 

foreach my $folder (@folderList) { 
    foreach my $word (@wordList) { 
      print "Searching for this $word in this $folder\n"; 

      my $pid = fork(); 
      if ($pid == 0) { # child process 
       # we are just printing output from the child process; if you want 
       # to move data from the child process back to the parent, well, 
       # that's a whole other can of worms 
       print `grep -R $word $folder`; 
       exit; 
      } else {   # parent process 
       while (waitpid($pid, &WNOHANG) != $pid) { 
        if (Term::ReadKey(-1)) { 
         kill 'TERM', $pid; # or maybe kill 'KILL', ... 
         last; 
        } 
       } 
      } 
    } 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^