2017-01-21 25 views
5

Tôi rất mới để lập trình perl.Các giá trị được in trong báo cáo foreach như thế nào?

Trong khi đọc về các vòng lặp, vòng lặp foreach tôi có hai ví dụ.

Một ví dụ là,

foreach ('hickory','dickory','doc') { 
    print $_; 
    print "\n"; 
} 

Output: -

hickory 
dickory 
doc 

Các $ _ biến chứa mỗi mục. Vì vậy, nó in.

Trong ví dụ khác, họ cho biết đã không chỉ định biến $ _ trong báo cáo in. Bản in trống chỉ có ở đó. Làm thế nào nó in các đối số foreach.

foreach ('hickory','dickory','doc') { 
    print; 
    print "\n"; 
} 

Output: -

hickory 
dickory 
doc 

Đối cũng cùng đầu ra này. Làm thế nào nó in các giá trị. Trong cuốn sách đó họ không đưa ra lời giải thích nào cho điều đó. Tôi đã được tìm kiếm trên internet. Nhưng tôi không thể tìm thấy bất cứ điều gì.

+6

Xem [perldoc -f print] (http://perldoc.perl.org/functions/print.html): * Nếu LIST bị bỏ qua, hãy in $ _ vào thanh công cụ đầu ra hiện đang được chọn. * '$ _' là đối số mặc định cho việc in, nghĩa là nếu bạn chỉ gọi 'print' mà không có đối số,' $ _' sẽ được in. – Dada

+2

Xem về '$ _' trong [Biến chung trong perlvar] (http://perldoc.perl.org/perlvar.html#General-Variables). Có những điều _many_ trong Perl sử dụng nó như mặc định, và nó là một trong những _the_ thiết bị phổ biến nhất. – zdim

+1

Có ai định viết câu trả lời không? Đó là một câu hỏi hợp lệ, mặc dù đọc tài liệu là đủ. Chỉ cần tìm tài liệu cụ thể đó là khó. Về cơ bản, chúng tôi có câu trả lời với các nhận xét ở trên nhưng nhận xét không phải là câu trả lời. Tôi sẽ đợi trong trường hợp một trong các bạn quyết định viết câu trả lời. – simbabque

Trả lời

5

Câu hỏi của bạn về print trong foreach đang được trả lời, đây là một chút nữa trên $_.

Từ General Variables in perlvar

Dưới đây là những nơi Perl sẽ giả $_ ngay cả khi bạn không sử dụng nó:

  • Các chức năng sau sử dụng $_ như một đối số mặc định:

    • abs, báo thức, chomp, chop, chr, chroot, cos, được xác định, eval, evalbytes, exp, fc, glob, hex, int, lc, lcfirst, length, log, lstat, mkdir, oct, ord, pos, print, printf, quotemeta, readlink, readpipe, ref, yêu cầu, ngược lại (trong ngữ cảnh vô hướng), rmdir, nói, sin, split (cho đối số thứ hai), sqrt, stat, nghiên cứu, uc, ucfirst, bỏ liên kết, giải nén.
  • Tất cả các bài kiểm tra tập tin (-f, -d) trừ -t, mặc định là STDIN. Xem -X

  • phù hợp với Các mô hình hoạt động m//, s///tr/// (aka y///) khi được sử dụng mà không cần một nhà điều hành =~.

  • Biến lặp mặc định trong vòng lặp foreach nếu không có biến nào khác được cung cấp.

  • Biến lặp tiềm ẩn trong các hàm grep()map().

  • Biến tiềm ẩn của given().

  • Nơi mặc định để đưa giá trị tiếp theo hoặc hồ sơ đầu vào khi kết quả một <FH>, readline, readdir hoặc each hoạt động được kiểm tra bởi chính nó như là tiêu chí duy nhất của một thử nghiệm while. Bên ngoài thử nghiệm while, điều này sẽ không xảy ra.

  • $_ theo mặc định là biến toàn cục.

Như bạn thấy, nó có sẵn gần khắp mọi nơi, và nó thực sự được sử dụng rất nhiều. Lưu ý rằng trang perlvar mô tả nhiều biến tương tự hơn, nhiều trong số đó là tốt để biết.

Đây là một ví dụ. Hãy xem xét rằng chúng ta đọc các dòng từ một tệp, muốn loại bỏ các dòng chỉ có dấu cách hoặc bắt đầu bằng # (nhận xét) và cho những người khác muốn tách chúng theo khoảng trắng thành các từ.

open my $fh, '<', $file or die "Can't open $file: $!"; 

while (<$fh>) 
{ 
    next if not /\S/; 
    next if /^\s*#/; 

    my @words = split; 

    # do something with @words ... 
} 

Hãy xem có bao nhiêu công dụng của $_ là trong ví dụ trên. Dưới đây là một chương trình tương đương

while (my $line = <$fh>) 
{ 
    next if not $line =~ m/\S/; # if not matching any non-space character 
    next if $line =~ m/^\s*#/;  # if matching # after only (possible) spaces 

    my @words = split ' ', $line; # split $line by ' ' (any white space) 

    # do something with @words ... 
} 

Hãy so sánh hai

  • filehandle đọc <$fh> trong điều kiện while gán để $_, sau đó có sẵn trong vòng lặp.

  • Cụm từ thông dụng toán tử đối sánh theo mặc định hoạt động trên $_. Bản thân số m có thể bị xóa.

  • split theo chia tách mặc định $_. Chúng tôi cũng sử dụng giá trị mặc định khác cho mẫu để chia chuỗi theo, là ' ' (bất kỳ số lượng khoảng trắng nào).

  • khi chúng tôi làm $line = <$fh> thỏa thuận với $_ bị tắt (không xác định trong vòng lặp) và chúng tôi phải sử dụng $line ở mọi nơi. Vì vậy, hoặc làm điều này hoặc làm while (<$fh>) và sử dụng $_.

Để minh họa cho tất cả điều này một chút nữa, chúng ta hãy tìm ra chữ viết hoa dài nhất trên mỗi dòng

use List::Util 'max'; 

my $longest_cap = max map { length } grep { /^[A-Z]/ } @words; 

Các grep mất danh sách trong @words và áp dụng các khối để mỗi phần tử. Mỗi mục được gán cho $_ và do đó có sẵn cho mã bên trong khối là $_. Đây là những gì regex sử dụng theo mặc định. Những cái thỏa mãn điều kiện được chuyển đến map, cũng lặp lại việc gán chúng cho $_, tất nhiên điều gì là mặc định cho length. Cuối cùng, max từ List::Util chọn cái lớn nhất.

Lưu ý rằng $_ không bao giờ thực sự được viết và không cần biến tạm thời.

Dưới đây là một số tài liệu liên quan. I/O Operators in perlop thảo luận về while (<$fh>) và tất cả các cách liên quan. Phần regex nằm trong Regexp Quote-Like Operators in perlop và trong perlretut. Ngoài ra, hãy xem split.


Mặc định được sử dụng thường xuyên và đọc mã do người khác viết, bạn phải hiểu chúng. Khi bạn viết mã của riêng bạn mặc dù bạn có thể chọn sử dụng $_ hay không, vì người ta luôn có thể giới thiệu một biến từ vựng thay vì nó.

Vì vậy, khi nào sử dụng $_ làm mặc định (không cần viết) và khi nào thì không?

Sử dụng đúng mặc định, $_ nói riêng, có thể dẫn đến mã rõ ràng hơn và dễ đọc hơn. Điều thường có nghĩa là mã số tốt hơn. Nhưng nó là khá tốt để đẩy điều này quá xa và kết thúc với mã mờ, khó khăn, và giòn. Vì vậy, hương vị tốt là cần thiết.

Trường hợp khác là khi một số phần của mã hưởng lợi từ việc có $_ cho các giá trị mặc định của chúng trong khi ở những nơi khác thì bạn phải sử dụng $_ một cách rõ ràng. Tôi muốn nói rằng nếu $_ được xem nhiều hơn một hoặc hai lần trong một đoạn mã, điều đó có nghĩa là phải có một biến được đặt tên đúng.

Nhìn chung, nếu nghi ngờ chỉ cần đặt tên cho mọi thứ.

2

Nếu bạn không khai báo bất kỳ biến trong foreach vòng lặp của bạn nó đặt theo mặc định $_

Từ perldoc about foreach:

Các foreach từ khóa thực sự là một từ đồng nghĩa với các từ khóa, vì vậy bạn có thể sử dụng hoặc. Nếu VAR bị bỏ qua, $ _ được đặt thành từng giá trị.

Vì vậy, giải thích vòng lặp đầu tiên.

Vòng lặp thứ hai, như bạn đã biết rằng $_ được đặt với từng phần tử từ mảng của bạn, sẽ hoạt động vì bạn đang bỏ qua $ var.

Bạn có thể sử dụng vòng lặp foreach với biến rõ ràng như thế này:

foreach my $item (@list) 
{ 

print "My item is: $item\n"; 

} 

Hoặc bạn có thể bỏ qua như bạn đã làm và print vẫn sẽ làm việc như @Dada nói vì:

Nếu filehandle được bỏ qua , in tới lựa chọn cuối cùng (xem chọn) xử lý đầu ra. Nếu DANH SÁCH bị bỏ qua, in $ _ vào thanh công cụ hiện tại được chọn .

0

tôi sẽ giải thích lý do tại sao bạn nhận được kết quả tương tự với cú pháp khác nhau:

Nếu bạn bỏ qua các biến điều khiển từ đầu foreach vòng lặp, Perl sử dụng biến mặc định vị trí của nó, $ _. Đây là (chủ yếu) giống như bất kỳ biến vô hướng nào khác, ngoại trừ tên bất thường của nó.Ví dụ:

foreach ('hickory','dickory','doc') { 
    print $_; 
    print "\n"; 
} 

Output:

hickory 
dickory 
doc 

Mặc dù đây không phải là mặc định chỉ Perl bằng một shot dài, đó là mặc định phổ biến nhất của Perl. Bạn sẽ thấy nhiều trường hợp khác, trong đó Perl sẽ tự động sử dụng $ _ khi bạn không nói nó sử dụng một số biến hoặc giá trị khác, do đó, lưu trình lập trình từ công việc nặng nhọc phải suy nghĩ và nhập tên biến mới. Vì vậy, khi không để giữ cho bạn trong hồi hộp, một trong những trường hợp đó là in, mà sẽ in $ _ nếu được không lập luận khác:

foreach ('hickory','dickory','doc') { 
    print; # prints $_ by default 
    print "\n"; 
} 

Output: -

hickory 
dickory 
doc 
Các vấn đề liên quan