2009-12-15 31 views
6

Tôi cần chạy một chuỗi thông qua một chương trình Java và sau đó truy xuất đầu ra. Chương trình Java chấp nhận chuỗi thông qua đầu vào tiêu chuẩn. Các công trình sau:Làm cách nào để tôi có thể nhập đường dẫn vào lệnh Java từ Perl?

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

Có một vấn đề: $string có thể là bất cứ thứ gì. Bất kỳ suy nghĩ về một giải pháp tốt cho vấn đề này?

Trả lời

6

tôi đề nghị bạn nhìn vào IPC::Run3 module. Nó sử dụng giao diện rất đơn giản và cho phép nhận STDERRSTDOUT. Dưới đây là ví dụ nhỏ:

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"; 

Xem IPC::Run3comparation with other modules.

6

Nếu bạn có thể sử dụng các mô-đun CPAN (và tôi giả định hầu hết mọi người có thể), hãy xem Ivan's answer khi sử dụng IPC::Run3. Nó sẽ xử lý mọi thứ bạn cần.

Nếu bạn không thể sử dụng các mô-đun, dưới đây là cách thực hiện mọi thứ theo cách vani đơn giản.

Bạn có thể sử dụng một ống để làm đầu vào của bạn, và nó sẽ tránh được tất cả những vấn đề trích dẫn dòng lệnh:

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

Dường như bạn thực sự cần đầu ra của lệnh, mặc dù. Bạn có thể mở hai ống với một cái gì đó như IPC::Open2 (đến và từ quá trình java) nhưng bạn có nguy cơ đặt mình vào bế tắc cố gắng để đối phó với cả hai đường ống cùng một lúc.

Bạn có thể tránh điều đó bằng cách sản lượng java vào một tập tin, sau đó đọc từ tập tin đó:

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); 

Các tùy chọn khác là để làm mọi thứ theo cách khác xung quanh. Đặt chuỗi $ vào một tệp tạm thời, sau đó sử dụng nó làm đầu vào cho 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); 

Lưu ý rằng đây không phải là cách tốt nhất để làm tệp tạm thời; Tôi vừa mới sử dụng output.txtinput.txt để đơn giản. Hãy xem File::Temp docs để biết các cách dọn dẹp khác nhau để tạo các tệp tạm thời một cách rõ ràng hơn.

+0

Điều đó có vẻ tuyệt vời nhưng làm cách nào để có được kết quả đầu ra của lệnh? – spudly

+1

@spudly, bạn không thể có đề xuất đó. Bạn cần phải sử dụng open2(), kiểm tra perldoc perlipc cho "giao tiếp hai chiều" – jsoverson

+0

Nhiều công dụng của open2 hoặc open3 trên các hệ thống Windows bị cản trở bởi thực tế là bạn chỉ có thể 'chọn' đối với một socket trên Win32. Nếu bạn không ở trên Windows hoặc chặn là ok, thì open2 hoặc open3 có thể làm thủ thuật cho bạn. – daotoad

1

IPC được xây dựng :: Mô-đun Open2 cung cấp chức năng xử lý đường ống hai chiều mà không có tệp bên ngoài.

2

Bạn đã xem xét IPC::Run?

Cú pháp tương tự như điều này có thể được những gì bạn đang tìm kiếm:

use IPC::Run qw(run); 
my $input = $string; 
my ($out, $err); 
run ["java -jar java_program.jar"], \$input, \$out, \$err; 
2

Tạo một đường ống giống như vỏ của bạn.

Dưới đây là chuỗi đáng sợ của chúng tôi:

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

Chúng tôi sẽ xây dựng đường ống dẫn của chúng tôi về phía sau, vì vậy đầu tiên chúng tôi thu thập kết quả từ chương trình 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"; 
    } 
} 

Lưu ý đặc biệt "-|" lập luận để Perl của open nhà điều hành.

Nếu bạn mở một đường ống trên lệnh '-', tức, hoặc '|-' hoặc '-|' với 2 đối số (hoặc 1 đối số) dưới dạng open(), sau đó là một tiềm ẩn fork thực hiện, và giá trị trả về của open là pid của đứa trẻ trong quá trình cha mẹ, và 0 trong quá trình con ... Filehandle cư xử bình thường cho cha mẹ, nhưng i/o để tập tin đó là đường ống từ/đến STDOUT/STDIN của quá trình con.

unpack để xem nội dung dữ liệu được đọc từ đường ống.

Trong chương trình của bạn, bạn sẽ muốn chạy các chương trình Java, nhưng mã dưới đây sử dụng một fax hợp lý:

else { 
    my $pid2 = open my $fh2, "-|"; 
    die "$0: fork: $!" unless defined $pid2; 

    if ($pid2) { 
    $| = 1; 
    open STDIN, "<&=" . fileno($fh2) 
     or die "$0: dup: $!"; 

    # exec "java", "-jar", "java_program.jar"; 

    # simulate Java program 
    exec "perl", "-pe", q(
     BEGIN { $" = "][" } 
     my @a = split " ", scalar reverse $_; 
     $_ = "[@a]\n"; 
    ); 
    die "$0: exec failed"; 
    } 

Cuối cùng, cháu khiêm tốn chỉ đơn giản in chuỗi đáng sợ (mà đến trên tiêu chuẩn đầu vào của chương trình Java) và thoát. Đặt $| thành giá trị thực sẽ xóa tập tin được chọn hiện tại và đặt nó ở chế độ không bị chặn.

else { 
    print $str; 
    $| = 1; 
    exit 0; 
    } 
} 

đầu ra của nó:

 
$ ./try 
[*][zab][][rab][~][*][oof] 
    => 91 42 93 91 122 97 98 93 91 0 93 91 114 97 98 93 91 126 93 91 42 93 91 111 111 102 93 

Lưu ý rằng NUL sống sót sau chuyến đi.

Các vấn đề liên quan