2009-07-14 15 views
5

Tôi nhận được dòng mã lạ này ngày hôm nay, nó cho tôi biết 'trống' hoặc 'không trống' tùy thuộc vào việc CWD có bất kỳ mục nào (ngoài số ...) trong đó.Làm thế nào để một lớp lót Perl này kiểm tra xem một thư mục có trống không?

Tôi muốn biết nó hoạt động như thế nào vì nó không có ý nghĩa với tôi.

perl -le 'print+(q=not =)[2==(()=<.* *>)].empty' 

Bit mà tôi quan tâm là <.* *>. Tôi không hiểu làm thế nào nó được tên của tất cả các tập tin trong thư mục.

+0

Hãy thoải mái chỉnh sửa các thẻ cho một cái gì đó phù hợp hơn – dsm

+3

Haha, bạn rất vui nhộn! Tôi lăn trên sàn cười. Bạn gọi là tiếng ồn dòng Perl !!!! HAHAHAHAHAHAHAHAHAHAHAHAHA! – jrockway

+0

Nộp đơn tuyệt vời cho 'làm xáo trộn năm'. Tôi thích Perl, nhưng tôi thậm chí còn giống như ý kiến ​​trong mã Perl. – Boldewyn

Trả lời

16

Đó là một chiếc áo lót lót gôn. Cờ -e có nghĩa là thực hiện phần còn lại của dòng lệnh làm chương trình. -l cho phép xử lý dòng tự động.

Phần <.* *> là hình cầu chứa hai mẫu để mở rộng: .**.

phần này

(q=not =) 

là một danh sách có chứa một giá trị duy nhất - chuỗi "không". Các q=...= là một dấu phân cách chuỗi thay thế, rõ ràng được sử dụng bởi vì các báo giá duy nhất đang được sử dụng để báo giá một lót.

Phần [...] là chỉ số trong danh sách đó. Giá trị của chỉ số dưới sẽ hoặc là 0 (giá trị "không  ") hoặc 1 (không có gì, mà in như chuỗi rỗng) tùy thuộc vào kết quả của sự so sánh này:

2 == (()=<.* *>) 

Có rất nhiều xảy ra ở đây. Việc so sánh kiểm tra xem liệu glob có trả về danh sách chính xác hai mục (giả định là ...) hay không nhưng nó hoạt động thế nào. Các dấu ngoặc đơn bên trong biểu thị một danh sách trống. Gán vào danh sách này đặt glob trong ngữ cảnh danh sách để nó trả về tất cả các tệp trong thư mục. (Trong ngữ cảnh vô hướng, nó sẽ hoạt động giống như một trình lặp và chỉ trả về một lần.) Bản thân nhiệm vụ được đánh giá trong ngữ cảnh vô hướng (ở phía bên phải của phép so sánh) và do đó trả về số phần tử được gán.

Hàng đầu + là để ngăn Perl phân tích cú pháp danh sách dưới dạng đối số thành print.Đường nhỏ .empty nối chuỗi "trống" vào bất kỳ thứ gì xuất hiện trong danh sách (ví dụ: "không phải là  " hoặc chuỗi trống).

+1

+1 lời giải thích ngắn gọn, ngắn gọn – hillu

+0

Đó là một chút gây hiểu lầm. Các bên trong() làm cho nó một danh sách nhiệm vụ, trong đó cung cấp cho bên phải của nó danh sách operand bối cảnh, nhưng nó chỉ có thể là tốt (2 == (@ a = <.* *>)). – ysth

+0

@ysth: Tôi không chắc tại sao bạn nghĩ đó là điều gây hiểu nhầm. Vì không có gì trong '()' bên trong nên danh sách bị loại bỏ. Mục đích của dấu ngoặc đơn (từ quan điểm của lập trình viên) là áp đặt bối cảnh danh sách trên glob. Anh ta có thể đã gán cho một mảng thay vì (IMO rõ ràng hơn) nhưng anh ta không làm vậy. Hoặc bạn đang đề cập đến một thực tế là nhiệm vụ trống thay đổi ngữ nghĩa từ "một danh sách trong ngữ cảnh vô hướng trả về phần tử cuối cùng" để "danh sách chuyển nhượng trả về số lượng các yếu tố"? Tôi có lẽ nên chỉnh sửa câu trả lời để làm rõ rằng ... –

3

<.* *> có nghĩa là (glob(".*"), glob("*")). glob mở rộng các mẫu tệp giống như cách trình bao làm.

7
<.* *> 

là một glob gồm hai mô hình: .* là tất cả các tên tập tin bắt đầu bằng .* tương ứng với tất cả các file (đây là khác biệt so với các công ước DOS/Windows thông thường).

(()=<.* *>) 

đánh giá ngữ cảnh trong danh sách, trả về tất cả tên tệp phù hợp.

Sau đó, so sánh với 2 đặt nó vào ngữ cảnh vô hướng để 2 được so sánh với số lượng tệp được trả về. Nếu số đó là 2, thì các mục nhập thư mục duy nhất là ..., dấu chấm. ;-)

0

Tài liệu về tính năng đó là here. (Di chuyển gần cuối của phần này)

+2

Tính năng nào? Đây có phải là một nhận xét cho câu trả lời của ai đó không? – Telemachus

+0

@Telemachus: <> có nghĩa là glob, có lẽ là. – ysth

+0

@Telemachus: Tài liệu cho glob/<>, như @ysth đã đề cập – dsm

2

tôi thấy rằng các mô-đun B::Deparse giúp khá nhiều trong việc giải mã một số nội dung mà ném ra mắt hầu hết các lập trình viên, chẳng hạn như các q=...= xây dựng:

$ perl -MO=Deparse,-p,-q,-sC 2>/dev/null << EOF 
> print+(q=not =)[2==(()=<.* *>)].empty 
> EOF 
use File::Glob(); 
print((('not ')[(2 == (() = glob('.* *')))] . 'empty')); 

Dĩ nhiên , điều này không ngay lập tức tạo ra "có thể đọc được" mã, nhưng nó chắc chắn chuyển đổi một số các trở ngại.

+0

Heh. Không có số lượng deparsing sẽ de-obfuscate việc sử dụng một boolean để chỉ mục vào một danh sách vô danh. [anti-pedantry: Vâng, tôi biết rằng "danh sách ẩn danh" là thừa.] –