Подтвердить что ты не робот

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

Я хочу получить выход из командной строки Windows (скажем, powercfg -l), записанный в файл, созданный с помощью Perl, а затем прочитать файл строки за строкой в ​​цикле for и назначить его строке.

4b9b3361

Ответ 1

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
}

Ответ 2

system 'powercfg', '-l';

- рекомендуемый способ. Если вы не возражаете против нереста подоболочки,

system "powercfg -l";

тоже будет работать. И если вы хотите получить результаты в строке:

my $str = `powercfg -l`;

Ответ 3

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

use strict;
use warnings;

open(my $fh, '-|', 'powercfg -l') or die $!;
while (my $line = <$fh>) {
    # Do stuff with each $line.
}

Ответ 4

Нет необходимости сначала сохранять вывод команды в файле:

my $output = `powercfg -l`;

См. qx// в Цитата -операторы.

Однако, если вы хотите сначала сохранить вывод в файле, вы можете использовать:

my $output_file = 'output.txt';

system "powercfg -l > $output_file";

open my $fh, '<', $output_file 
    or die "Cannot open '$output_file' for reading: $!";

while ( my $line = <$fh> ) {
    # process lines
}

close $fh;

См. perldoc -f system.

Ответ 5

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

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

Взгляните на запись perlport для system. Вы можете использовать system( 1, 'command line to run'); для создания дочернего процесса и продолжения script.

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

Я проверил это в случае с 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;
}

Ответ 6

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

ПРИМЕЧАНИЕ: backticks `` сообщают 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 упрощает работу!

Ответ 7

Попробуйте использовать оператоp > для пересылки вывода в файл, например:

powercfg -l > output.txt

И затем откройте файл output.txt и обработайте его.