2011-02-08 25 views
6

Tôi đang cố mở tệp nhận được làm đối số.Perl: Mở tệp

Khi tôi lưu đối số vào biến toàn cục mở hoạt động thành công.

Nhưng

Nếu tôi sử dụng cho làm cho nó càng mở của tôi thất bại trong việc mở tập tin.

Lý do là gì.

#use strict; 
use warnings; 

#my $FILE=$ARGV[0]; #open Fails to open the file $FILE 

$FILE=$ARGV[0];  #Works Fine with Global $FILE 
open(FILE) 
    or 
die "\n ". "Cannot Open the file specified :ERROR: $!". "\n"; 
+6

Kiểu perl này là ** cách ** lỗi thời. Bạn sẽ tốt hơn nhiều khi mở tập tin $ của tôi, "<", $ ARGV [0] ... hoặc tốt hơn nhưng không gọi mở và chỉ đọc từ ARGV.(Perl giả định các đối số là các tệp được mở cho đầu vào và mở chúng tự động cho bạn.) –

+1

Mở một cách duy nhất được ghi lại để chỉ hoạt động trên các biến gói. – tchrist

+0

@William: Không có mã hóa ở đó? 'mở (FH," <: mã hóa (UTF-8) ", $ pathname)' – tchrist

Trả lời

13

Chỉ hoạt động mở một cách độc lập trên các biến gói (toàn cầu). Đây là tài liệu trên the manpage.

Cách tốt hơn để mở một tập tin để đọc sẽ là:

my $filename = $ARGV[0];   # store the 1st argument into the variable 
open my $fh, '<', $filename or die $!; # open the file using lexically scoped filehandle 

print <$fh>; # print file contents 

T.B. luôn sử dụng strictwarnings trong khi gỡ lỗi tập lệnh Perl của bạn.

+2

Câu trả lời này bỏ lỡ điểm. Câu hỏi đơn giản là lý do tại sao công việc mở đơn nhất chỉ với các biến gói. Câu trả lời đơn giản là bởi vì nó được ghi nhận như vậy. Tất cả những thứ khác là phủ sương trên một chiếc bánh mất tích. – tchrist

+0

@tchrist: ok, tôi đã thêm câu trả lời này vào câu trả lời –

+0

Cảm ơn. Tôi thường không downvote câu trả lời đã thực hiện một thử tốt ở đó (đó là lý do tại sao tôi đã không làm như vậy ở đây). Tôi thích chỉ ra những gì họ đã bỏ lỡ. Cảm ơn bạn đã sửa chữa nó. – tchrist

7

Đó là tất cả trong perldoc -f open:

Nếu EXPR được bỏ qua, các biến vô hướng cùng tên như filehandle chứa tên tập tin. (Lưu ý rằng từ vựng biến - những khai báo với "tôi" - sẽ không làm việc cho mục đích này, vì thế nếu bạn đang sử dụng "của tôi", xác định EXPR trong lệnh gọi để mở.)

Lưu ý rằng đây không phải là cách hay để chỉ định tên tệp. Như bạn có thể thấy, nó có một ràng buộc khó khăn về kiểu biến nó ở trong, và cả biến toàn cục mà nó yêu cầu hoặc tập tin toàn cục mà nó mở ra thường là tốt nhất nên tránh.

Sử dụng một filehandle từ vựng giữ phạm vi của nó trong kiểm soát, và xử lý đóng cửa tự động:

open my $fh, '<', "filename" or die "string involving $!"; 

Và nếu bạn đang dùng rằng tên tập tin từ dòng lệnh, bạn có thể có thể loại bỏ mà open hoặc bất kỳ xử lý hoàn toàn và sử dụng toán tử đơn giản <> để đọc từ các đối số dòng lệnh hoặc STDIN. (xem nhận xét để biết thêm về điều này)

+0

Điểm tốt: Thường là tốt hơn rất nhiều để sử dụng ma thuật ARGV hơn là mở một cách rõ ràng. Nhưng thêm 'if (! @ARGV && -t STDIN) {cảnh báo" $ 0: đọc từ stdin ... \ n "}' để giúp những người có hệ thống thiếu '' T' tty char. Tuy nhiên, ma thuật ARGV chỉ sử dụng stdin khi '@ ARGV' ban đầu trống rỗng, không phải khi nó cạn kiệt; câu trả lời của bạn cho thấy khác. – tchrist

+0

@tchrist: có và không ... sau khi '<>' ARGV cạn kiệt và quay trở lại undef một lần (những gì bạn đang nói), nó sẽ bắt đầu lại, với một @ARGV trống nếu bạn không làm bất cứ điều gì về nó, do đó rơi trở lại STDIN (những gì tôi đã nói). Tôi muốn thừa nhận hầu hết mọi người sẽ không vượt qua được một cách tự nhiên đầu tiên và chỉnh sửa. –

+0

Um, tôi ** làm ** biết cách '<>' hoạt động. :) – tchrist

6
use strict; 
use warnings; 

my $file_name = shift @ARGV; 
open(my $file, '<', $file_name) or die $!; 
… 
close($file); 

Luôn sử dụng strictwarnings. Nếu một trong hai người đó than phiền, hãy sửa mã, đừng bình luận ra các pragmas. Bạn cũng có thể use autodie để tránh rõ ràng or die sau khi mở, xem autodie.

+1

+1 và nó cần phải được nói một lần nữa: Nếu 'strict' than phiền, điều đó có nghĩa là bạn cần phải sửa mã của bạn, không phải là bạn cần phải bình luận ra' strict'. –

+0

Tôi đã nói điều đó trước đây, tôi sẽ nói lại lần nữa: * Câu trả lời này bỏ lỡ vấn đề. Câu hỏi đơn giản là lý do tại sao công việc mở đơn nhất chỉ với các biến gói. Câu trả lời đơn giản là bởi vì nó được ghi nhận như vậy. Ngoài ra, bạn quên chỉ định mã hóa như trong 'mở (FH," <: encoding (UTF-8) ", $ path)'. Và nếu một người đang rất cẩn thận, chẳng phải ai cũng nên thử nghiệm '@ ARGV' vì sự hợp lý? Cuối cùng, làm thế nào bạn có thể biết họ làm ** KHÔNG ** muốn cho phép tên tập tin như '-' trong thời trang Unix chuẩn xác định std {in, out, whatever}? – tchrist

+1

Ngoài ra, đây là một thành ngữ thực sự xấu. Perl đã xử lý tự động mở các tệp được liệt kê dưới dạng đối số qua ARGV. Trong perl, hầu như không bao giờ có lý do chính đáng để mở một tệp có tên trong @ARGV –

3

Từ Perl's docs for open()

Nếu EXPR được bỏ qua, các biến vô hướng của tên giống như filehandle chứa tên tập tin. (Lưu ý rằng các biến từ vựng - những biến được khai báo với tôi - sẽ không hoạt động cho mục đích này, vì vậy nếu bạn đang sử dụng, hãy chỉ định EXPR trong cuộc gọi của bạn để mở.)

+0

gọn gàng, chính xác và cho điểm. – tchrist