Как я могу передать вход по каналу в команду Java от Perl?

Я должен выполнить строку через программу Java и затем получить вывод. Программа Java принимает строку через стандартный вход. Следующие работы:

my $output = `echo $string | java -jar java_program.jar`;

Существует одна проблема: $string могло быть примерно что-либо. Какие-либо мысли о хорошем решении этой проблемы?

6
задан brian d foy 16 December 2009 в 09:39
поделиться

5 ответов

Предлагаю вам посмотреть модуль IPC :: Run3 . Он использует очень простой интерфейс и позволяет получить STDERR и STDOUT . Вот небольшой пример:

use IPC::Run3;
## store command output here
my ($cmd_out, $cmd_err);
my $cmd_input = "put your input string here";
run3([ 'java', '-jar', 'java_program.jar'], \$cmd_input, \$cmd_out, \$cmd_err);
print "command output [$cmd_out] error [$cmd_err]\n";

См. IPC :: Run3 сравнение с другими модулями .

6
ответ дан 8 December 2019 в 13:46
поделиться

Если вы можете использовать модули CPAN (а я предполагаю, что большинство людей могут), посмотрите ответ Ивана об использовании IPC :: Run3 . Он должен обрабатывать все, что вам нужно.

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

Вы можете использовать конвейер для ввода данных, и это позволит избежать всех этих цитирований командной строки issues:

open PIPE, "| java -jar java_program.jar";
print PIPE "$string";
close(PIPE);

Похоже, вам действительно нужен вывод команды. Вы могли открыть два канала с помощью чего-то вроде IPC :: Open2 (в и из java-процесса), но вы рискуете попасть в тупик, пытаясь иметь дело с обоими каналами одновременно.

Этого можно избежать, если вывести java-файл в файл, а затем читать из этого файла:

open PIPE, "| java -jar java_program.jar > output.txt";
print PIPE "$string";
close(PIPE);

open OUTPUT, "output.txt";
while (my $line = <OUTPUT>) {
    # do something with $line
}
close(OUTPUT);

Другой вариант - сделать все наоборот. Поместите $ string во временный файл, затем используйте его как входные данные для java:

open INPUT, "input.txt";
print INPUT "$string";
close(INPUT); 

open OUTPUT, "java -jar java_program.jar < input.txt |";
while (my $line = <OUTPUT>) {
    # do something with the output
}
close(OUTPUT);

Обратите внимание, что это не лучший способ создания временных файлов; Я только что использовал output.txt и input.txt для простоты. Прочтите File :: Temp docs , чтобы узнать о различных способах более чистого создания временных файлов.

6
ответ дан 8 December 2019 в 13:46
поделиться

Вы изучали IPC :: Run ?

Возможно, вы ищете синтаксис, подобный этому:

use IPC::Run qw( run );
my $input = $string;
my ($out, $err);
run ["java -jar java_program.jar"], \$input, \$out, \$err;
2
ответ дан 8 December 2019 в 13:46
поделиться

Создайте конвейер просто как и ваша оболочка.

Вот наша страшная строка:

my $str = "foo * ~ bar \0 baz *";

Мы построим конвейер в обратном направлении, поэтому сначала мы соберем выходные данные программы Java:

my $pid1 = open my $fh1, "-|";
die "$0: fork: $!" unless defined $pid1;

if ($pid1) {
  # grab output from Java program
  while (<$fh1>) {
    chomp;
    my @c = unpack "C*" => $_;
    print "$_\n  => @c\n";
  }
}

Обратите внимание на специальный "- |" для оператора Perl open .

Если вы открываете канал по команде '-' , т.е. , либо '| -' или '- |'

2
ответ дан 8 December 2019 в 13:46
поделиться

Встроенный модуль IPC :: Open2 предоставляет функцию для обработки двунаправленных каналов без внешнего файла.

1
ответ дан 8 December 2019 в 13:46
поделиться
Другие вопросы по тегам:

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