ความแตกต่างระหว่าง backticks ระบบและ exec ของ Perl คืออะไร


237

มีใครช่วยได้บ้าง ใน Perl ความแตกต่างระหว่าง:

exec "command";

และ

system("command");

และ

print `command`;

มีวิธีอื่นในการรันคำสั่งเชลล์ด้วยหรือไม่


8
เกือบจะซ้ำซ้อนกับstackoverflow.com/questions/797127/…ยกเว้นว่าอันนี้มี exec และอีกอันหนึ่งมีท่อ
Michael Myers

คำตอบ:


268

exec

รันคำสั่งและไม่เคยให้ผลตอบแทน มันเหมือนreturnคำสั่งในฟังก์ชั่น

หากไม่พบคำสั่งจะexecส่งคืนค่าเท็จ มันจะไม่ส่งคืนจริงเพราะถ้าพบคำสั่งมันจะไม่ส่งกลับเลย นอกจากนี้ยังมีจุดใดในการกลับมาSTDOUT, STDERRหรือออกจากสถานะของคำสั่ง คุณสามารถค้นหาเอกสารเกี่ยวกับมันใน perlfuncเพราะมันเป็นฟังก์ชั่น

ระบบ

รันคำสั่งและสคริปต์ Perl ของคุณจะดำเนินการต่อหลังจากคำสั่งเสร็จสิ้น

ค่าส่งคืนคือสถานะออกของคำสั่ง perlfuncคุณสามารถค้นหาเอกสารเกี่ยวกับมันใน

backticks

เช่นsystemรันคำสั่งและสคริปต์ Perl ของคุณจะดำเนินต่อไปหลังจากคำสั่งเสร็จสิ้น

ตรงกันข้ามกับsystemค่าส่งคืนเป็นSTDOUTของคำสั่ง qx//เทียบเท่ากับ backticks คุณสามารถค้นหาเอกสารเกี่ยวกับมันได้perlopเนื่องจากไม่เหมือนsystemและexecเป็นผู้ดำเนินการ


ทางอื่น

สิ่งที่หายไปจากด้านบนเป็นวิธีการดำเนินการคำสั่งแบบอะซิงโครนัส นั่นหมายความว่าสคริปต์ Perl และคำสั่งของคุณทำงานพร้อมกัน openนี้สามารถทำได้ด้วย อนุญาตให้คุณอ่านSTDOUT/ STDERRและเขียนSTDINคำสั่งของคุณ มันขึ้นอยู่กับแพลตฟอร์มว่า

นอกจากนี้ยังมีอีกหลายโมดูลที่สามารถทำให้งานนี้ง่าย มีIPC::Open2และIPC::Open3และIPC::Runเช่นเดียวกับ Win32::Process::Createถ้าคุณอยู่บน windows


1
ฉันคิดว่าคุณหมายถึง s / perlcunc / perlfunc / ... นอกจากนี้ยังมีเอกสาร perlipc ที่มีความลึกมากเกี่ยวกับการเปิดท่อ
ephemient

7
perlcunc อาจนี้จะเป็นชื่อใหม่ของฉันกรงขัง ;-)
Ludwig Weinzierl

8
สำหรับเร็กคอร์ด backticks และ qx [] ยังเติมเงิน $ ด้วยหรือไม่ (ค่าส่งคืนของระบบปฏิบัติการ)
jjohn

167

ในการใช้งานทั่วไป I system, open, IPC::Open2หรือIPC::Open3ขึ้นอยู่กับสิ่งที่ฉันต้องการจะทำ qx//ผู้ประกอบการในขณะที่ง่ายเกินไป constraining ในการทำงานของที่จะอยู่นอกมีประโยชน์มากของแฮ็กได้อย่างรวดเร็ว ฉันพบว่าopenมีความชำนาญมากกว่า

system: เรียกใช้คำสั่งและรอให้คำสั่งส่งคืน

ใช้systemเมื่อคุณต้องการเรียกใช้คำสั่งไม่สนใจเกี่ยวกับเอาต์พุตและไม่ต้องการให้สคริปต์ Perl ทำอะไรจนกว่าคำสั่งจะเสร็จสิ้น

#doesn't spawn a shell, arguments are passed as they are
system("command", "arg1", "arg2", "arg3");

หรือ

#spawns a shell, arguments are interpreted by the shell, use only if you
#want the shell to do globbing (e.g. *.txt) for you or you want to redirect
#output
system("command arg1 arg2 arg3");

qx//หรือ `` : เรียกใช้คำสั่งและจับ STDOUT ของมัน

ใช้qx//เมื่อคุณต้องการเรียกใช้คำสั่งจับภาพสิ่งที่เขียนไปยัง STDOUT และไม่ต้องการให้สคริปต์ Perl ทำอะไรจนกว่าคำสั่งจะเสร็จสิ้น

#arguments are always processed by the shell

#in list context it returns the output as a list of lines
my @lines = qx/command arg1 arg2 arg3/;

#in scalar context it returns the output as one string
my $output = qx/command arg1 arg2 arg3/;

exec: แทนที่กระบวนการปัจจุบันด้วยกระบวนการอื่น

ใช้execคู่กับforkเมื่อคุณต้องการเรียกใช้คำสั่งไม่สนใจเกี่ยวกับเอาต์พุตและไม่ต้องการรอให้คำสั่งส่งคืน systemเป็นเพียงแค่จริงๆ

sub my_system {
    die "could not fork\n" unless defined(my $pid = fork);
    return waitpid $pid, 0 if $pid; #parent waits for child
    exec @_; #replace child with new process
}

คุณอาจต้องการอ่านwaitpidและperlipcคู่มือ

open: เรียกใช้กระบวนการและสร้างไพพ์ไปยัง STDIN หรือ STDERR

ใช้openเมื่อคุณต้องการเขียนข้อมูลไปยัง STDIN ของกระบวนการหรืออ่านข้อมูลจาก STDOUT ของกระบวนการ (แต่ไม่ใช่ทั้งสองอย่างในเวลาเดียวกัน)

#read from a gzip file as if it were a normal file
open my $read_fh, "-|", "gzip", "-d", $filename
    or die "could not open $filename: $!";

#write to a gzip compressed file as if were a normal file
open my $write_fh, "|-", "gzip", $filename
    or die "could not open $filename: $!";

IPC :: Open2 : เรียกใช้กระบวนการและสร้างไปป์ทั้ง STDIN และ STDOUT

ใช้IPC::Open2เมื่อคุณต้องการอ่านและเขียนไปยัง STDIN และ STDOUT ของกระบวนการ

use IPC::Open2;

open2 my $out, my $in, "/usr/bin/bc"
    or die "could not run bc";

print $in "5+6\n";

my $answer = <$out>;

IPC :: Open3 : เรียกใช้กระบวนการและสร้างไปป์ STDIN, STDOUT และ STDERR

ใช้IPC::Open3เมื่อคุณต้องการจับกระบวนการจัดการไฟล์มาตรฐานทั้งสามตัว ฉันจะเขียนตัวอย่าง แต่มันก็ใช้งานได้เหมือนกันกับ IPC :: Open2 แต่ส่วนใหญ่แล้วจะเรียงตามลำดับของอาร์กิวเมนต์และตัวจัดการไฟล์ตัวที่สาม


ข้อมูลที่มากและไม่เกินคำตอบ ขอบคุณ @ chas-owens
Jassi

IPC :: Open3 อยู่ในระดับต่ำเกินไปสำหรับการใช้งานส่วนใหญ่ IPC :: Run3 และ IPC :: Run มักจะเหมาะสมกว่า
ikegami

17

ให้ฉันพูดคู่มือก่อน:

perldoc exec () :

ฟังก์ชั่น exec ดำเนินการคำสั่งระบบและไม่กลับ - ใช้ระบบแทนexecถ้าคุณต้องการที่จะกลับมา

ระบบ perldoc () :

ทำสิ่งเดียวกันกับ exec LIST ยกเว้นว่าจะทำ forkก่อนและกระบวนการพาเรนต์จะรอให้กระบวนการลูกสมบูรณ์

ตรงกันข้ามกับexecและระบบ backticks ไม่ให้ค่าตอบแทน แต่เป็น STDOUT ที่รวบรวมไว้

perldoc `String` :

สตริงซึ่งเป็น (อาจ) สอดแทรกแล้วดำเนินการเป็นคำสั่งระบบที่มี/ bin / shหรือเทียบเท่า สัญลักษณ์แทนของเชลล์ไพพ์และการเปลี่ยนเส้นทางจะได้รับการยกย่อง ที่เก็บรวบรวมได้ออกมาตรฐานของคำสั่งจะถูกส่งกลับ ; ข้อผิดพลาดมาตรฐานไม่ได้รับผลกระทบ


ทางเลือก:

ในสถานการณ์ที่ซับซ้อนมากขึ้นที่คุณต้องการดึงข้อมูล STDOUT, STDERR หรือรหัสส่งคืนคุณสามารถใช้ที่รู้จักกันดีโมดูลมาตรฐานเช่นIPC :: Open2และIPC :: Open3

ตัวอย่าง:

use IPC::Open2;
my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'some', 'cmd', 'and', 'args');
waitpid( $pid, 0 );
my $child_exit_status = $? >> 8;

ในที่สุดIPC :: เรียกใช้จาก CPAN ก็คุ้มค่าที่จะดู ...


3
นี่คือการตอบกลับที่หยาบคาย คุณควรพยายามช่วยเหลือคุณโดยไม่โกรธ
Shane C. Mason

1
ฉันคิดว่าเขากำลังอ้างอิงถึง ol 'RTFM: P
v3

ไม่ได้หมายความว่าหยาบคายจริง;) ออก F-คำว่าเพื่อหลีกเลี่ยงความเข้าใจผิดใด ๆ ...
เบเน Waldvogel

2
แน่นอนฉันไม่ได้ตีความว่ามันหยาบคาย บางที Brusque แต่นี่ไม่ใช่คำถามที่ฉลาดมากที่ต้องการคำตอบที่รอบคอบ
ephemient

11

ความแตกต่างระหว่าง backticks ของ Perl (คน`) systemและexec?

exec -> exec "command"; ,
system -> system("command"); and 
backticks -> print `command`;

exec

execรันคำสั่งและไม่ดำเนินการสคริปต์ Perl ต่อ มันเป็นสคริปต์เหมือนreturnคำสั่งคือฟังก์ชั่น

หากไม่พบคำสั่งให้execส่งคืน false มันจะไม่ส่งคืนจริงเพราะถ้าพบคำสั่งมันจะไม่ส่งกลับเลย นอกจากนี้ยังมีจุดใดในการกลับมาSTDOUT, STDERRหรือออกจากสถานะของคำสั่ง คุณสามารถค้นหาเอกสารเกี่ยวกับมันในperlfuncเพราะมันเป็นฟังก์ชั่น

เช่น:

#!/usr/bin/perl
print "Need to start exec command";
my $data2 = exec('ls');
print "Now END exec command";
print "Hello $data2\n\n";

ในรหัสข้างต้นมีสามprintคำสั่ง แต่เนื่องจากexecออกจากสคริปต์จะมีการดำเนินการคำสั่งพิมพ์ครั้งแรกเท่านั้น นอกจากนี้execเอาต์พุตคำสั่งไม่ได้ถูกกำหนดให้กับตัวแปรใด ๆ

ที่นี่มีเพียงคุณเท่านั้นที่ได้รับผลลัพธ์ของprintคำสั่งแรกและการดำเนินการlsคำสั่งตามมาตรฐาน

system

systemรันคำสั่งและสคริปต์ Perl ของคุณจะกลับมาทำงานต่อหลังจากคำสั่งเสร็จสิ้น ค่าส่งคืนคือสถานะออกของคำสั่ง คุณสามารถค้นหาเอกสารเกี่ยวกับมันในperlfunc

เช่น:

#!/usr/bin/perl
print "Need to start system command";
my $data2 = system('ls');
print "Now END system command";
print "Hello $data2\n\n";

ในรหัสข้างต้นมีสามprintคำสั่ง เมื่อสคริปต์ทำงานต่อหลังจากsystemคำสั่งคำสั่งการพิมพ์ทั้งสามจะถูกดำเนินการ

นอกจากนี้ผลของการทำงานsystem จะได้รับมอบหมายให้data2แต่ค่าที่ได้รับมอบหมายเป็น0(รหัสการออกจากls)

ที่นี่คุณจะได้รับผลลัพธ์ของprintคำสั่งแรกจากนั้นlsตามด้วยคำสั่งตามด้วยผลลัพธ์ของสองคำสั่งสุดท้ายprintคำสั่งที่ออกมาตรฐาน

backticks ( `)

เช่นsystemล้อมรอบคำสั่งใน backticks รันคำสั่งนั้นและสคริปต์ Perl ของคุณจะกลับมาทำงานต่อหลังจากคำสั่งเสร็จสิ้น ตรงกันข้ามกับsystemค่าส่งคืนเป็นSTDOUTคำสั่ง qx//เทียบเท่ากับ backticks คุณสามารถค้นหาเอกสารเกี่ยวกับมันในperlopเพราะแตกต่างจากระบบและexecมันเป็นผู้ประกอบการ

เช่น:

#!/usr/bin/perl
print "Need to start backticks command";
my $data2 = `ls`;
print "Now END system command";
print "Hello $data2\n\n";

ในรหัสข้างต้นมีสามprintคำสั่งและทั้งสามกำลังถูกดำเนินการ เอาต์พุตของlsจะไม่ออกมาตรฐานโดยตรง แต่กำหนดให้กับตัวแปรdata2แล้วพิมพ์โดยคำสั่งพิมพ์สุดท้าย


คำอธิบายที่ดีที่สุดพร้อมตัวอย่าง ขอบคุณมาก.
Arslan Anwar

2

ความแตกต่างระหว่าง 'exec' และ 'system' คือ exec แทนที่โปรแกรมปัจจุบันของคุณด้วย 'command' และไม่กลับสู่โปรแกรมของคุณ ในทางกลับกันส้อมและรัน 'คำสั่ง' และส่งคืนสถานะการออกของ 'คำสั่ง' เมื่อคุณรันเสร็จแล้ว เครื่องหมายขีดด้านหลังรัน 'คำสั่ง' จากนั้นส่งคืนสตริงที่แทนค่ามาตรฐาน (สิ่งที่มันจะพิมพ์ไปที่หน้าจอ)

คุณยังสามารถใช้ popen เพื่อรันคำสั่งเชลล์และฉันคิดว่ามีโมดูลเชลล์ - 'use shell' ที่ให้คุณเข้าถึงคำสั่งเชลล์ทั่วไปได้อย่างโปร่งใส

หวังว่าจะชี้แจงให้คุณ


บางทีคุณอาจหมายถึงuse Shell;( search.cpan.org/dist/Shell/Shell.pm )? มันไม่ได้ติดตั้งกันอย่างแพร่หลายและไม่เป็นมันที่ใช้บังคับกับคำถามที่ฉันคิดว่า ...
ephemient

1
ส่วนสุดท้ายของคำถามของเขาคือ "มีวิธีอื่นในการเรียกใช้คำสั่งเชลล์ด้วย" - เชลล์เป็นอีกวิธีในการเรียกใช้คำสั่งเชลล์
Shane C. Mason

2
เอกสารระบุเป็นพิเศษ "แพคเกจนี้รวมเป็นกรณีแสดงซึ่งแสดงให้เห็นถึงคุณสมบัติของ Perl บางอย่างไม่ควรใช้สำหรับโปรแกรมที่ใช้งานจริงแม้ว่าจะให้อินเทอร์เฟซที่เรียบง่ายสำหรับการรับเอาท์พุทมาตรฐานของคำสั่งตามอำเภอใจ วิธีในการบรรลุสิ่งที่คุณต้องการ "
Chas Owens

2
อีกครั้งก็ตอบคำถามของเขา 'จะมีวิธีการอื่น ๆ'
เชนซีเมสัน

ไม่ควรมอบวิธีที่ไม่ดีและไม่ได้รับการสนับสนุนโดยไม่มีการเตือนว่าเป็นวิธีที่ไม่ดีและไม่ได้รับการสนับสนุน
Chas Owens
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.