2012-04-01 14 views
5

Tôi muốn biết về các phương pháp hay nhất tại đây. Giả sử tôi muốn lấy nội dung của một số dòng của một tập tin. Tôi có thể sử dụng một lệnh shell một dòng để có được câu trả lời của tôi, hoặc viết một chương trình con, như trong đoạn mã dưới đây.Trong kịch bản Perl, chúng ta có nên sử dụng các lệnh shell hay gọi các hàm Perl mà bắt chước các hoạt động của trình bao?

Một tập tin văn bản có tên some_text:

She laughed. Then both continued eating in silence, like strangers, 
but after dinner they walked side by side; and there sprang up 
between them the light jesting conversation of people who are free 
and satisfied, to whom it does not matter where they go or what 
they talk about. 

Mã để có được nội dung của dòng 5 của tập tin

#!perl 
use warnings; 
use strict; 

my $file = "some_text"; 
my $lnum = 5; 
my $shellcmd = "awk 'NR==$lnum' $file"; 
print qx($shellcmd); 
print getSrcLine($file, $lnum); 

sub getSrcLine { 
    my($file, $lnum) = @_; 
    open FILE, $file or die "$!"; 
    my @ray = <FILE>; 
    return $ray[$lnum-1]; 
} 

Tôi yêu cầu này bởi vì tôi nhìn thấy rất nhiều kịch bản Perl nơi tại một số điểm, một lệnh shell được gọi, trong khi tại một số điểm sau đó, cùng một nhiệm vụ được thực hiện bằng một cuộc gọi đến một hàm (thư viện hoặc viết tay), ví dụ, rm -rf so với File::Path::rmtree. Tôi chỉ muốn làm cho nó phù hợp.

Bạn nên làm gì?

+0

Cách được khuyên dùng tùy thuộc vào ý định của mã.Nếu bạn muốn thực thi trên máy Unix không thì hãy đi với các thư viện perl khác xem liên kết tôi đã đăng .. Hy vọng điều này sẽ giúp .. – Rajeev

+0

Có thể mỗi tập lệnh được phát triển trong một khoảng thời gian, có thể bởi nhiều lập trình viên. Các kịch bản phát triển, và mã không phải là 100% tự nhất quán, tùy thuộc một phần vào cách những người tham gia có nhiều kinh nghiệm với Perl và shell. –

+2

Lưu ý rằng trong khi slurping một tập tin toàn bộ 5 dòng để có được dòng thứ năm không phải là quá đau đớn, nó có lẽ là một chiến lược phụ tối ưu để nhận được dòng thứ năm của một tập tin triệu dòng. –

Trả lời

13

Nếu có chức năng Perl cho hoạt động, Perl cho rằng bạn nên sử dụng phiên bản của nó. Tuy nhiên, bạn đưa ra một ví dụ về một mô-đun Perl cung cấp một cách Perl tinh khiết để thực hiện điều đó. Điều đó khác nhiều. Không có câu trả lời duy nhất (như trong hầu hết mọi thứ), vì vậy bạn phải tự quyết định phải làm gì:

  • Phương pháp Perl thuần túy có làm đúng không? Ví dụ, File::Copy có một số hạn chế bởi vì nó làm cho một số quyết định khó xử cho người dùng, vì vậy nhiều người nghĩ rằng nó bị hỏng. Xem, ví dụ: File::Copy versus cp/mv.

  • Cách tiếp cận Perl thuần túy có hoạt động trong thời gian chấp nhận được không? Đôi khi các chương trình bên ngoài là đơn đặt hàng của cường độ nhanh hơn. Đôi khi nó chậm hơn rất nhiều.

  • Lệnh bên ngoài thường di chuyển trong một nhóm hệ thống (ví dụ: tất cả các hệ thống giống như Linux) nhưng có thể không nằm trong các gia đình (ví dụ: Windows và Linux). Sự khoan dung của bạn cho điều đó có thể ảnh hưởng đến câu trả lời của bạn. Ngay cả khi bạn nghĩ rằng bạn đang chạy cùng một lệnh, các hương vị khác nhau của các hệ thống giống như Unix có thể có các công tắc khác nhau cho các hoạt động.

  • Truyền các đối số phức tạp — dấu cách, dấu ngoặc kép và các ký tự đặc biệt — đến các lệnh bên ngoài có thể khiến bạn khóc. Bạn phải làm rất nhiều công việc khó khăn để đảm bảo rằng bạn đang xử lý các đối số một cách chính xác. Perl chương trình con không quan tâm mặc dù.

  • Bạn phải chú ý nhiều hơn đến những gì bạn đang làm khi bạn đang sử dụng lệnh bên ngoài. Nếu bạn chỉ cần gọi rm, Perl sẽ tìm kiếm thông qua PATH của bạn và sử dụng thứ đầu tiên được gọi là rm. Điều đó không có nghĩa đó là chương trình bạn nghĩ. Tôi viết về điều này khá một chút trong "Kỹ thuật lập trình an toàn" trong Làm chủ Perl.

  • Nếu cách tiếp cận Perl thuần túy yêu cầu một mô-đun, đặc biệt nếu mô-đun đó có nhiều phụ thuộc phức tạp, bạn có thể đang ở trạng thái phụ thuộc hoặc phân phối xuống đường.

Cá nhân, tôi bắt đầu với phương pháp Perl thuần túy cho đến khi nó không hoạt động cho tình huống.

Ví dụ cụ thể của bạn, tôi sẽ sử dụng Perl. Shelling ra để awk, mà là một proto-Perl, chỉ là lẻ. Bạn sẽ có thể làm mọi thứ awk làm đúng nó Perl. Nếu bạn có một chương trình awk, bạn có thể chuyển nó sang Perl với chương trình A2P:

NR==5 

A2P biến đó vào (modulo một số bit thiết lập lúc bắt đầu):

while (<>) { 
    print $_ if $. == 5; 
} 

ý rằng nó vẫn quét toàn bộ tệp ngay cả khi bạn có dòng thứ năm. Tuy nhiên, bạn có thể sử dụng chương trình đã dịch như là một sự khởi đầu:

while (<>) { 
    if($. == 5) { 
     print; 
     last; 
     } 
} 

Tôi không nghĩ bạn nên bỏ qua một số chương trình khác để tránh mã Perl đó.

Để xóa cây thư mục, tôi thích File::Path. Nó có một số phụ thuộc, nhưng chúng đều nằm trong Thư viện chuẩn Perl. Có rất ít đau, nếu có, liên kết với mô-đun đó. Tôi sẽ sử dụng nó cho đến khi tôi gặp phải một vấn đề mà nó không hoạt động.

+0

cảm ơn bạn đã trả lời chi tiết. Tôi thích điểm về an ninh nói riêng, vì tôi không xem xét nó rất nhiều trong khi mã hóa trong Perl. Ngoài ra, tôi đã gặp chương trình a2p, thật sự rất tiện dụng! Tôi tin rằng bây giờ tôi nên cố gắng tránh các lệnh shell bên ngoài trong các kịch bản của tôi miễn là Perl có thể làm điều tương tự một cách đáng tin cậy. – Unos

+0

Câu trả lời hay. Việc bổ sung duy nhất tôi sẽ làm là liên quan đến các yêu cầu của kịch bản. Nếu bạn đang viết một chương trình sử dụng một lần, việc kích hoạt lệnh * nix là khá hợp lý nếu nó tiết kiệm cho bạn bất cứ lúc nào. Gần đây, tôi đã thực hiện việc này trên một tập lệnh dữ liệu mang tính cơ bản cho tập lệnh xuất-nhập-dữ liệu của Datbase. Nó nhanh hơn để mở ra một lệnh bên ngoài cho một phần của nó, và kịch bản sẽ bị vứt bỏ sau khi nó chạy (đúng) một lần. Nếu tôi viết một chương trình có chức năng tương tự mỗi tuần, tôi đã dành thời gian để thực hiện nó đúng cách trong Perl, nếu tôi có thể. –

4

Nếu bạn muốn ứng dụng của mình được di chuyển sang các hệ thống không có hệ thống, hãy chắc chắn mã hóa mọi thứ trong Perl.

Nếu không, điều đó thực sự tùy thuộc vào bạn ... việc tạo quy trình mới sẽ chậm hơn, nhưng nếu nó không quan trọng đối với tác vụ thì điều đó cũng không quan trọng. Cá nhân tôi sẽ chọn giải pháp mà tôi có thể triển khai nhanh hơn.

2

Dường như với tôi rằng mã hoạt động phải là ưu tiên hàng đầu. Bạn không thành công nếu tên tệp có một khoảng trống trong đó, ví dụ.

Sử dụng trình bao làm cho mã khó hơn khi chương trình của bạn cần tạo đúng chương trình khác để chạy bởi sh. (Vấn đề này sẽ biến mất nếu bạn sử dụng hệ thống đa arg để tránh vỏ.)

Hơn nữa, việc sử dụng các công cụ bên ngoài có thể gây khó khăn cho việc xử lý lỗi. Bạn thậm chí không cố gắng làm như vậy!

Mặt khác, có nhiều lý do để sử dụng các công cụ bên ngoài. Ví dụ: Perl không cung cấp tiện ích sao chép tệp tốt như cp; sử dụng công cụ sort cho phép bạn sắp xếp các tệp lớn tùy ý với RAM giới hạn; vv

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