2012-06-21 20 views
15

Perl cung cấp tính năng này rất đẹp:Perl: Cách lấy tên tệp khi sử dụng <> cấu trúc?

while (<>) 
{ 
    # do something 
} 

... cho phép các kịch bản được sử dụng như script.pl <filename> cũng như cat <filename> | script.pl.

Bây giờ, có cách nào để xác định xem tập lệnh có được gọi theo cách cũ hay không và nếu có, tên tệp là gì?

Tôi biết tôi biết điều này một lần, và tôi biết tôi thậm chí còn sử dụng cấu trúc, nhưng tôi không thể nhớ vị trí/cách thức. Và nó đã chứng minh rất khó để tìm kiếm 'net cho điều này ("perl stdin filename"? Không ...).

Trợ giúp, vui lòng?

+2

bạn có thể làm điều đó bằng cách kiểm tra @ARGV không? – beresfordt

+1

Xin lỗi vì cái cũ/thứ hai, mà dường như đã gây ra một số nhầm lẫn. – DevSolar

+1

Bạn có thể tìm thấy hầu hết mọi thứ trong tài liệu. 'perldoc perlvar' chứa thông tin về' $ ARGV', ví dụ. – TLP

Trả lời

20

Biến số $ARGV giữ tệp hiện tại đang được xử lý.

$ echo hello1 > file1 
$ echo hello2 > file2 
$ echo hello3 > file3 
$ perl -e 'while(<>){s/^/$ARGV:/; print;}' file* 
file1:hello1 
file2:hello2 
file3:hello3 
+1

@Quentin: vẫn còn, đó là phần duy nhất của câu hỏi thực sự có thể xảy ra. – lanzz

+1

"cho phép tập lệnh được sử dụng dưới dạng tập lệnh' script.pl "..." Bây giờ, có cách nào để xác định xem tập lệnh đã được gọi theo cách trước đây "=> trước đây =>' script.pl filename' –

+1

... nhưng đó là câu trả lời đúng, như một bài kiểm tra nhanh được chứng minh. Một thử nghiệm thứ hai cho thấy '$ ARGV' chứa' -' nếu được cung cấp bởi một đường ống. – DevSolar

2

Nếu bạn quan tâm để biết về khi <> chuyển sang một file mới (ví dụ như trong trường hợp của tôi - Tôi muốn ghi tên tập tin mới và số dòng), sau đó các eof() function documentation cung cấp một thủ thuật:

# reset line numbering on each input file 
while (<>) { 
    next if /^\s*#/; # skip comments 
    print "$.\t$_"; 
} continue { 
    close ARGV if eof; # Not eof()! 
} 
+0

Đẹp! Không thực sự về chủ đề, nhưng tốt đẹp để biết tuy nhiên. – DevSolar

3

I/O Operators section of perlop rất thông tin về điều này.

Về cơ bản, lần đầu tiên <> được thực hiện, - được thêm vào @ARGV nếu nó bắt đầu trống. Mở - có tác dụng nhân bản bộ xử lý tệp STDIN và biến $ARGV được đặt thành phần tử hiện tại là @ARGV khi được xử lý.

Đây là clip đầy đủ.

Các filehandle null "<>" là đặc biệt: nó có thể được sử dụng để mô phỏng các hành vi của sed và awk, và bất kỳ chương trình lọc Unix khác mà phải mất một danh sách của tên tập tin, làm như vậy để mỗi dòng đầu vào từ tất cả các số chúng. Đầu vào từ "<>" xuất phát từ đầu vào tiêu chuẩn hoặc từ mỗi tệp được liệt kê trên dòng lệnh. Dưới đây là cách hoạt động: lần đầu tiên "<>" được đánh giá, mảng @ARGV được chọn và nếu trống, $ ARGV [0] được đặt thành "-", khi được mở cho phép bạn nhập chuẩn. Sau đó, mảng @ARGV được xử lý dưới dạng danh sách tên tệp. Vòng lặp

while (<>) { 
     ...      # code for each line 
    } 

tương đương với mã giả Perl giống như sau:

unshift(@ARGV, '-') unless @ARGV; 
    while ($ARGV = shift) { 
     open(ARGV, $ARGV); 
     while (<ARGV>) { 
      ...   # code for each line 
     } 
    } 

ngoại trừ việc nó không phải là quá cồng kềnh để nói, và thực sự sẽ làm việc. Nó thực sự chuyển mảng @ARGV và đặt tên tệp hiện tại vào biến số $ ARGV. Nó cũng sử dụng file handhandle ARGV trong nội bộ. "<>" chỉ là một từ đồng nghĩa cho "< ARGV>", điều này thật kỳ diệu. (Mã giả ở trên không hoạt động vì nó xử lý "< ARGV>" là phi huyền diệu.)

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