2010-10-29 18 views
7

Trong perldoc perlvar, tôi đọc:Làm thế nào tôi có thể cho biết một hàm Perl có tệp để đọc từ trình xử lý ARGV đặc biệt?

Lưu ý rằng hiện "argv" chỉ có hiệu ứng phép thuật của mình trong "<>" điều hành; ở những nơi khác, nó chỉ là một tệp ảnh đơn giản tương ứng với tệp cuối cùng được mở bởi "<>". Cụ thể, chuyển "* ARGV" làm tham số cho hàm dự kiến ​​một tệp có thể không làm cho chức năng của bạn thành tự động đọc nội dung của tất cả các tệp trong @ARGV.

Vì vậy, làm thế nào có thể tôi vượt qua *ARGV (hoặc cái gì đó tương tự như nó) như là một paramter để một chức năng mà hy vọng một filehandle, và có chức năng đọc tất cả các file trong @ARGV?

Trả lời

12

Đi thẳng về phía trước và vượt qua số *ARGV typeglob hoặc \*ARGV, tham chiếu của nó. Chỉ cần đảm bảo rằng chức năng cuối cùng sử dụng nó làm như vậy thông qua các nhà điều hành <$fh> hoặc readline($fh), tương đương chức năng cơ bản của nó.

Vấn đề này được đề cập trong đoạn văn trích dẫn từ manpage perlvar chỉ là cố gắng để nhắc nhở bạn rằng bạn sẽ không thể để có được ARGV 's kỳ diệu mở để kích hoạt nếu bạn sử dụng bất kỳ cơ chế đọc khác hơn readline trên xử lý, chẳng hạn như read, sysread hoặc getc.

Run này để chứng minh với bản thân nó hoạt động:

sub mycat { 
    my $fh = shift; 
    print "$ARGV $.: $_" while <$fh>; 
} 
mycat(*ARGV); 

Đặt rằng trong một tập tin, sau đó chạy nó với một số đối số file:

% perl mycat ./mycat //`pwd`/mycat ~/mycat 
./mycat 1: sub mycat { 
./mycat 2:  my $fh = shift; 
./mycat 3:  print "$ARGV $.: $_" while <$fh>; 
./mycat 4: } 
./mycat 5: mycat(*ARGV); 
///home/tchrist/mycat 6: sub mycat { 
///home/tchrist/mycat 7:  my $fh = shift; 
///home/tchrist/mycat 8:  print "$ARGV $.: $_" while <$fh>; 
///home/tchrist/mycat 9: } 
///home/tchrist/mycat 10: mycat(*ARGV); 
/home/tchrist/mycat 11: sub mycat { 
/home/tchrist/mycat 12:  my $fh = shift; 
/home/tchrist/mycat 13:  print "$ARGV $.: $_" while <$fh>; 
/home/tchrist/mycat 14: } 
/home/tchrist/mycat 15: mycat(*ARGV); 

Thấy không? Nó hoạt động tốt.

+1

Huh. Chương trình của tôi bắt đầu hoạt động sau khi tôi đọc nó. –

-1

Bạn có thể giả mạo nó với cat (trên một hệ thống Unix)

open FAKE_ARGV, "cat @ARGV |"; 
function_expecting_filehandle(*FAKE_ARGV); 
... 

Bạn mất một số sự kỳ diệu ($ARGV, $.) với điều này.

Tôi chắc chắn có cách để thực hiện với một tập tin đính kèm cũng vậy (xem perltie).

1

Bạn có thể redispatch để <> khi lặp lại một đối tượng quá tải:

{package ReadARGV; 
    sub new {bless []} 
    use overload '<>' => sub {<>}; 
} 

sub reader { 
    my $fh = shift; 
    local $_; 
    print while <$fh>; 
} 

reader(ReadARGV->new); 

Gói ReadARGV chứa một đối tượng xây dựng đơn giản new và sau đó làm quá tải các <HANDLE> vận hành chỉ cần gọi <>.