كيف يمكنني التقاط stdin وstdout لأمر النظام من برنامج Perl النصي؟

StackOverflow https://stackoverflow.com/questions/78091

  •  09-06-2019
  •  | 
  •  

سؤال

يوجد في منتصف البرنامج النصي لـ Perl أمر نظام أريد تنفيذه.لدي سلسلة تحتوي على البيانات التي يجب إدخالها في stdin (الأمر يقبل الإدخال من stdin فقط)، وأحتاج إلى التقاط الإخراج المكتوب إلى stdout.لقد ألقيت نظرة على الطرق المختلفة لتنفيذ أوامر النظام في Perl، و open يبدو أن الوظيفة هي ما أحتاج إليه، إلا أنه يبدو أنه يمكنني فقط التقاط stdin أو stdout، وليس كليهما.

في الوقت الحالي، يبدو أن الحل الأفضل بالنسبة لي هو الاستخدام open, ، وأعد توجيه stdout إلى ملف مؤقت، واقرأ من الملف بعد انتهاء الأمر.هل هناك حل أفضل؟

هل كانت مفيدة؟

المحلول

أعتقد أنك تريد أن تلقي نظرة على إي بي سي::فتح2

نصائح أخرى

IPC::Open2/3 جيد، لكنني وجدت أن كل ما أحتاجه عادةً هو IPC::Run3, ، الذي يتعامل مع الحالات البسيطة بشكل جيد وبأقل قدر من التعقيد:

use IPC::Run3;    # Exports run3() by default

run3( \@cmd, \$in, \$out, \$err );

تقارن الوثائق IPC::Run3 بالبدائل الأخرى.إنه يستحق القراءة حتى لو لم تقرر استخدامه.

ال وثائق بيرليبك يغطي العديد من الطرق التي يمكنك من خلالها القيام بذلك، بما في ذلك IPC::Open2 وIPC::Open3.

في مكان ما في الجزء العلوي من البرنامج النصي الخاص بك، قم بتضمين السطر

use IPC::Open2;

سيتضمن ذلك الوحدة الضرورية، والتي يتم تثبيتها عادةً مع معظم توزيعات Perl افتراضيًا.(إذا لم يكن لديك، يمكنك تثبيته باستخدام CPAN.) ثم، بدلاً من فتحه، اتصل:

$pid = open2($cmd_out, $cmd_in, 'some cmd and args');

يمكنك إرسال البيانات إلى الأمر الخاص بك عن طريق إرسالها إلى $cmd_in ثم قراءة مخرجات الأمر الخاص بك عن طريق القراءة من $cmd_out.

إذا كنت تريد أيضًا أن تكون قادرًا على قراءة تدفق الأمر stderr، فيمكنك استخدام وحدة IPC::Open3 بدلاً من ذلك.

IPC::Open3 من المحتمل أن يفعل ما تريد.يمكنه التقاط STDERR وSTDOUT.

http://metacpan.org/pod/IPC::Open3

طريقة سهلة جدًا للقيام بذلك والتي وجدتها مؤخرًا هي ال IPC::مرشح وحدة.يتيح لك القيام بالمهمة بشكل حدسي للغاية:

$output = filter $input, 'somecmd', '--with', 'various=args', '--etc';

لاحظ كيف يستدعي الأمر الخاص بك دون المرور عبر الصدفة إذا مررت له قائمة.كما أنه يقوم بعمل معقول في معالجة الأخطاء في المرافق العامة.(في حالة الفشل dies، باستخدام النص من STDERR كرسالة خطأ؛عند النجاح، يتم تجاهل STDERR للتو.)

بالطبع، إنها ليست مناسبة لكميات هائلة من البيانات لأنها لا توفر أي طريقة للقيام بأي معالجة متدفقة؛كما أن معالجة الأخطاء قد لا تكون دقيقة بما يكفي لتلبية احتياجاتك.لكنه يجعل العديد من الحالات البسيطة حقا حقًا بسيط.

هناك أمر بيرل خاص لذلك

open2()

يمكن العثور على مزيد من المعلومات على: http://sunsite.ualberta.ca/Documentation/Misc/perl-5.6.1/lib/IPC/Open2.html

إذا كنت لا ترغب في تضمين حزم إضافية، يمكنك القيام بذلك فقط

open(TMP,">tmpfile");
print TMP  $tmpdata ;
open(RES,"$yourcommand|");
$res = "" ;
while(<RES>){
$res .= $_ ;
}

وهو عكس ما اقترحته، ولكن يجب أن تعمل أيضا.

أفعل ذلك دائمًا بهذه الطريقة إذا كنت أتوقع سطرًا واحدًا فقط من الإخراج أو أرغب في تقسيم النتيجة على شيء آخر غير السطر الجديد:

my $result = qx( command args 2>&1 );  
my $rc=$?;  
# $rc >> 8 is the exit code of the called program.

if ($rc != 0 ) {  
    error();  
}  

إذا كنت تريد التعامل مع استجابة متعددة الأسطر، احصل على النتيجة كمصفوفة:

my @lines = qx( command args 2>&1 );  

foreach ( my $line ) (@lines) {  
    if ( $line =~ /some pattern/ ) {  
        do_something();  
    }  
}  
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top