Как получить вывод внешней команды в Perl?

Выяснил мою собственную проблему. Решение оказалось основано на интерполяторах.

Animation fadeIn = new AlphaAnimation(0, 1);
fadeIn.setInterpolator(new DecelerateInterpolator()); //add this
fadeIn.setDuration(1000);

Animation fadeOut = new AlphaAnimation(1, 0);
fadeOut.setInterpolator(new AccelerateInterpolator()); //and this
fadeOut.setStartOffset(1000);
fadeOut.setDuration(1000);

AnimationSet animation = new AnimationSet(false); //change to false
animation.addAnimation(fadeIn);
animation.addAnimation(fadeOut);
this.setAnimation(animation);
20
задан Jon Seigel 7 March 2010 в 18:21
поделиться

7 ответов

my $output = qx(powercfg -l);

## You've got your output loaded into the $output variable. 
## Still want to write it to a file?
open my $OUTPUT, '>', 'output.txt' or die "Couldn't open output.txt: $!\n";
print $OUTPUT $output;
close $OUTPUT

## Now you can loop through each line and
##   parse the $line variable to extract the info you are looking for.
foreach my $line (split /[\r\n]+/, $output) {
  ## Regular expression magic to grab what you want
}
22
ответ дан 29 November 2019 в 22:32
поделиться
system 'powercfg', '-l';

is the recommended way. If you don't mind spawning a subshell,

system "powercfg -l";

will work, too. And if you want the results in a string:

my $str = `powercfg -l`;
23
ответ дан 29 November 2019 в 22:32
поделиться

Поскольку OP запускает powercfg , он / она, вероятно, перехватывают выходные данные внешнего сценария, поэтому он / она, вероятно, не найдет этот ответ ужасно полезным. Этот пост в первую очередь написан для других людей, которые находят здесь ответы с помощью поиска.

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

Взгляните на запись perlport для системы . Вы можете использовать system (1, 'командная строка для запуска'); для создания дочернего процесса и продолжения вашего скрипта.

Это действительно очень удобно, но есть одно серьезное предупреждение: ] не задокументировано. Если вы запустите более 64 процессов за одно выполнение скрипта, ваши попытки запустить дополнительные программы потерпят неудачу.

Я проверил, что это относится к Windows XP и ActivePerl 5.6 и 5.8. Я не тестировал это с Vista, с Stawberry Perl или любой версией 5.10.

Вот один лайнер, который вы можете использовать для проверки вашего Perl на наличие этой проблемы:

C:\>perl -e "for (1..100) { print qq'\n $_\n-------\n'; system( 1, 'echo worked' ), sleep 1 }

Если проблема существует в вашей системе, вы будете для запуска многих программ вы можете использовать модуль Win32 :: Process для управления запуском вашего приложения.

Вот пример использования Win32 :: Process :

use strict;
use warnings;

use Win32::Process;

if( my $pid = start_foo_bar_baz() ) {
    print "Started with $pid";
}
:w

sub start_foo_bar_baz {

    my $process_object;  # Call to Create will populate this value.
    my $command = 'C:/foo/bar/baz.exe';  # FULL PATH to executable.
    my $command_line = join ' ',
           'baz',   # Name of executable as would appear on command line
           'arg1',  # other args
           'arg2';

    # iflags - controls whether process will inherit parent handles, console, etc.
    my $inherit_flags = DETACHED_PROCESS;  

    # cflags - Process creation flags.
    my $creation_flags = NORMAL_PRIORITY_CLASS;

    # Path of process working directory
    my $working_directory = 'C:/Foo/Bar';

    my $ok = Win32::Process::Create(
       $process_object,
       $command,
       $command_line,
       $inherit_flags,
       $creation_flags, 
       $working_directory,
    );

    my $pid;
    if ( $ok ) {
        $pid = $wpc->GetProcessID;
    }
    else {
        warn "Unable to create process: "
             . Win32::FormatMessage( Win32::GetLastError() ) 
        ;
        return;
    }

    return $pid;
}
2
ответ дан 29 November 2019 в 22:32
поделиться

У вас уже есть хорошие ответы. Кроме того, если вы просто хотите обработать вывод команды и вам не нужно отправлять этот вывод непосредственно в файл, вы можете установить канал между командой и вашим сценарием Perl.

use strict;
use warnings;

open(my $fh, '-|', 'powercfg -l') or die $!;
while (my $line = <$fh>) {
    # Do stuff with each $line.
}
24
ответ дан 29 November 2019 в 22:32
поделиться

There are a lot of good suggestions and ideas here and notice that there are different ways to tackle it for different purposes. Having used many serial protocols both good and bad as well having made several of my own (both good and bad...) here are a few of my suggestions and comments.

  • Keep it simple. I have found the greatest success with simple header на основе "пакетов" команд-ответов

  • Не беспокойтесь о читабельном коде ASCII. Это полезно только в течение нескольких часов, когда вы фактически отлаживаете свой протокол. После этого всегда запрещено кодировать данные как ASCII и очень неэффективно при передаче большого количества данных.

  • Используйте проверку ошибок. Я предпочитаю 16-битную CRC, поскольку она обеспечивает порядок защиты по сравнению с контрольной суммой и по-прежнему прост и эффективен по сравнению с более тяжелыми алгоритмами, такими как MD5 или SHA1.

  • Используйте тот же формат пакета для команд, что и для ответов.

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

  • Таким образом, в простейшей форме заголовок пакета - это команда или ответ, размер пакета, ноль или дополнительные данные и код проверки ошибок (CRC).

8
ответ дан 29 November 2019 в 22:32
поделиться

Чтобы расширить отличный ответ Синан и более подробно ответить на ваш вопрос:

ПРИМЕЧАНИЕ: обратные кавычки `` говорят Perl выполнить команду и получить ее вывод:

#!/usr/bin/perl -w
use strict;


my @output = `powercfg -l`;
chomp(@output); # removes newlines

my $linecounter = 0;    
my $combined_line;

foreach my $line(@output){
    print $linecounter++.")";
    print $line."\n"; #prints line by line

    $combined_line .= $line; # build a single string with all lines
    # The line above is the same as writing:
    # $combined_line = $combined_line.$line;
}

print "\n";
print "This is all on one line:\n";
print ">".$combined_line."<";

Ваш вывод (на моя система) будет выглядеть так:

0)
1)Existing Power Schemes (* Active)
2)-----------------------------------
3)Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e  (Balanced) *
4)Power Scheme GUID: 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c  (High performance)
5)Power Scheme GUID: a1841308-3541-4fab-bc81-f71556f20b4a  (Power saver)

This is all on one line:
>Existing Power Schemes (* Active)-----------------------------------Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e  (Balanced) *Power Scheme GUID: 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c  (High performance)Power Scheme GUID: a1841308-3541-4fab-bc81-f71556f20b4a  (Power saver)<

Perl упрощает работу!

2
ответ дан 29 November 2019 в 22:32
поделиться

Один из вариантов состоит в том, чтобы сообщения приходили с собственными обработчиками. То есть создайте интерфейс с именем IMessageProcessor, который определяет метод processMessage (IMessage). Затем определите конкретный класс, который реализует IMessageProcessor для каждого типа сообщения.

Каждый класс IMessage затем определит свой собственный процессор.

1
ответ дан 29 November 2019 в 22:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: