Tôi đã không nhận thức được giải thưởng cho đến ngày hôm nay khi một số tân binh cố gắng ghim UUOC vào tôi cho một trong những câu trả lời của tôi. Đó là một cat file.txt | grep foo | cut ... | cut ...
. Tôi đã cho anh ấy một phần suy nghĩ của tôi, và chỉ sau khi làm như vậy, đã truy cập vào liên kết mà anh ấy đã cho tôi đề cập đến nguồn gốc của giải thưởng và thực hành làm như vậy. Tìm kiếm thêm dẫn tôi đến câu hỏi này. Thật không may, mặc dù có ý thức xem xét không có câu trả lời nào bao gồm lý do của tôi.
Tôi không có ý phòng thủ khi giáo dục anh ta. Rốt cuộc, trong những năm còn trẻ, tôi đã viết lệnh grep foo file.txt | cut ... | cut ...
vì bất cứ khi nào bạn thường xuyên thực grep
hiện, bạn sẽ học được vị trí của đối số tệp và sẵn sàng biết rằng đầu tiên là mẫu và các mẫu sau là tên tệp.
Đó là một lựa chọn có ý thức khi tôi trả lời câu hỏi với cat
tiền tố một phần vì lý do "hương vị tốt" (theo lời của Linus Torvalds) nhưng chủ yếu là vì lý do thuyết phục của chức năng.
Lý do thứ hai là quan trọng hơn vì vậy tôi sẽ đưa nó ra trước. Khi tôi cung cấp một đường ống như một giải pháp, tôi hy vọng nó có thể được tái sử dụng. Rất có khả năng một đường ống sẽ được thêm vào cuối hoặc ghép vào một đường ống khác. Trong trường hợp đó, có một đối số tệp để grep tăng khả năng sử dụng lại và hoàn toàn có thể làm như vậy một cách im lặng mà không có thông báo lỗi nếu đối số tệp tồn tại. I E. grep foo xyz | grep bar xyz | wc
sẽ cung cấp cho bạn số lượng dòng xyz
chứa bar
trong khi bạn đang mong đợi số lượng dòng chứa cả foo
và bar
. Phải thay đổi đối số thành một lệnh trong một đường ống trước khi sử dụng nó dễ bị lỗi. Thêm vào đó là khả năng thất bại thầm lặng và nó trở thành một thực tiễn đặc biệt quỷ quyệt.
Lý do trước đây không phải là không quan trọng vì rất nhiều "hương vị tốt" chỉ là một lý do tiềm thức trực giác cho những thứ như những thất bại thầm lặng ở trên mà bạn không thể nghĩ ra ngay lúc mà một người cần giáo dục nói "nhưng không phải là con mèo đó vô dụng ".
Tuy nhiên, tôi sẽ cố gắng làm cho ý thức về lý do "hương vị tốt" trước đây tôi đã đề cập. Lý do đó phải làm với tinh thần thiết kế trực giao của Unix. grep
không cut
và ls
không grep
. Do đó ít nhất grep foo file1 file2 file3
đi ngược lại với tinh thần thiết kế. Cách trực giao làm việc đó là cat file1 file2 file3 | grep foo
. Bây giờ, grep foo file1
chỉ đơn thuần là một trường hợp đặc biệt grep foo file1 file2 file3
, và nếu bạn không đối xử với nó giống như vậy thì ít nhất bạn cũng đang sử dụng hết chu kỳ đồng hồ não để cố gắng tránh giải thưởng mèo vô dụng.
Điều đó dẫn chúng ta đến cuộc tranh luận về grep foo file1 file2 file3
sự kết hợp và cat
sự kết hợp sao cho phù hợp cat file1 file2 file3
nhưng vì cat
nó không được kết nối cat file1 | grep foo
do đó chúng ta đang vi phạm tinh thần của cả cat
Unix và toàn năng. Chà, nếu đó là trường hợp thì Unix sẽ cần một lệnh khác để đọc đầu ra của một tệp và nhổ nó vào thiết bị xuất chuẩn (không phân trang nó hoặc bất cứ thứ gì chỉ là nhổ thuần túy vào thiết bị xuất chuẩn). Vì vậy, bạn sẽ có tình huống bạn nói cat file1 file2
hoặc bạn nói dog file1
và nhớ một cách tận tâm cat file1
để tránh nhận giải thưởng, đồng thời tránh dog file1 file2
vì hy vọng thiết kế dog
sẽ gây ra lỗi nếu nhiều tệp được chỉ định.
Hy vọng rằng tại thời điểm này, bạn đồng cảm với các nhà thiết kế Unix vì không bao gồm một lệnh riêng biệt để nhổ một tệp vào thiết bị xuất chuẩn, đồng thời đặt tên cat
cho concatenate thay vì đặt cho nó một số tên khác. <edit>
Có một con chó như vậy, người <
điều hành không may . Thật không may là vị trí của nó ở cuối đường ống ngăn cản khả năng kết hợp dễ dàng. Không có cách tổng hợp hoặc thẩm mỹ để đặt nó ở đầu. Thật không may khi không đủ chung chung để bạn bắt đầu với con chó nhưng chỉ cần thêm một tên tệp khác nếu bạn cũng muốn nó được xử lý sau cái trước đó. (Mặt >
khác, không phải là một nửa xấu. Nó có vị trí gần như hoàn hảo ở cuối. Nó thường không phải là một phần có thể tái sử dụng của một đường ống, và do đó nó được phân biệt một cách tượng trưng.)</edit>
Câu hỏi tiếp theo là tại sao điều quan trọng là phải có các lệnh chỉ nhổ một tệp hoặc ghép một số tệp vào thiết bị xuất chuẩn mà không cần xử lý thêm? Một lý do là để tránh việc mỗi lệnh Unix hoạt động trên đầu vào tiêu chuẩn phải biết cách phân tích ít nhất một đối số tệp dòng lệnh và sử dụng nó làm đầu vào nếu nó tồn tại. Lý do thứ hai là để tránh người dùng phải nhớ: (a) nơi các đối số tên tệp đi; và (b) tránh lỗi đường ống im lặng như đã đề cập ở trên.
Điều đó đưa chúng ta đến lý do tại sao grep
có logic bổ sung. Lý do là cho phép người dùng lưu loát cho các lệnh được sử dụng thường xuyên và trên cơ sở độc lập (chứ không phải là một đường ống). Đó là một sự thỏa hiệp nhỏ về tính trực giao để đạt được đáng kể khả năng sử dụng. Không phải tất cả các lệnh phải được thiết kế theo cách này và các lệnh không được sử dụng thường xuyên sẽ tránh hoàn toàn logic bổ sung của các đối số tệp (hãy nhớ logic bổ sung dẫn đến sự mong manh không cần thiết (khả năng xảy ra lỗi)). Ngoại lệ là cho phép đối số tệp như trong trường hợp grep
. (bằng cách lưu ý rằng ls
có một lý do hoàn toàn khác để không chỉ chấp nhận mà còn yêu cầu khá nhiều đối số tệp)
Cuối cùng, những gì có thể được thực hiện tốt hơn là nếu các lệnh đặc biệt như grep
(nhưng không nhất thiết ls
) tạo ra lỗi nếu đầu vào tiêu chuẩn có sẵn. Điều này là hợp lý bởi vì các lệnh bao gồm logic vi phạm tinh thần trực giao của Unix toàn năng để thuận tiện cho người dùng. Để thuận tiện hơn cho người dùng, tức là để ngăn chặn sự đau khổ do lỗi im lặng gây ra, các lệnh như vậy không nên ngần ngại vi phạm chính họ bằng cách cảnh báo cho người dùng nếu có khả năng xảy ra lỗi im lặng.