Tại sao `sort <phiên bản $ F1 'được ưa thích hơn` sắp xếp


29

Từ https://unix.stackexchange.com/a/458074/674

Nhớ sử dụng -- khi chuyển các đối số tùy ý cho các lệnh (hoặc sử dụng chuyển hướng nếu có thể). Vì vậy, sort -- "$f1"hoặc tốt hơn sort < "$f1"thay vì sort "$f1".

Tại sao nó được ưa thích để sử dụng --và chuyển hướng?

Tại sao được sort < "$f1"ưa thích hơn sort -- "$f1"?

Tại sao được sort -- "$f1"ưa thích hơn sort "$f1"?

Cảm ơn.


Câu trả lời:


55
sort "$f1"

không thành công cho các giá trị $f1bắt đầu bằng -hoặc ở đây đối với trường hợp sortmột số bắt đầu bằng +(có thể gây hậu quả nghiêm trọng cho một tệp được gọi là -o/etc/passwdchẳng hạn).

sort -- "$f1"

(nơi -- báo hiệu sự kết thúc của các tùy chọn) giải quyết hầu hết các vấn đề đó nhưng vẫn không thành công cho tệp được gọi -(thay vào đó sortdiễn giải là stdin của nó).

sort < "$f1"

Không có những vấn đề đó.

Đây là cái vỏ mở tập tin. Điều đó cũng có nghĩa là nếu tệp không thể được mở, bạn cũng sẽ nhận được thông báo lỗi hữu ích hơn (ví dụ: hầu hết các shell sẽ chỉ ra số dòng trong tập lệnh) và thông báo lỗi sẽ nhất quán nếu bạn sử dụng chuyển hướng bất cứ nơi nào có thể để mở tập tin.

Và trong

sort < "$f1" > out

(trái với sort -- "$f1" > out), nếu "$f1"không thể mở, outsẽ không được tạo / cắt và sortthậm chí không chạy.

Để xóa một số nhầm lẫn có thể xảy ra (theo các bình luận bên dưới), điều đó không ngăn lệnh mmap()nhập tệp hoặc lseek()vào bên trong tệp (không phải điều sortđó) với điều kiện là bản thân tệp có thể tìm kiếm được. Sự khác biệt duy nhất là tệp được mở trước đó và trên bộ mô tả tệp 0 bằng vỏ trái ngược với lệnh sau có thể trên một bộ mô tả tệp khác. Lệnh vẫn có thể tìm kiếm / mmap mà fd 0 khi nó vừa ý. Điều đó không có gì khó hiểu cat file | cmdkhi cmdstdin lần này là một đường ống không thể được ghép / tìm kiếm.


4
Chỉ cần nhớ rằng sử dụng một lực chuyển hướng sortđể đọc dữ liệu tuần tự và bạn không thể mmaptập tin. Trong khi sortcó thể không có nhiều vấn đề với nó, hãy xem xét hiệu suất của less <fileless file. Trong trường hợp đầu tiên lessphải giữ toàn bộ nội dung của tệp trong bộ nhớ, trong trường hợp thứ hai, nó chỉ được phép đọc những phần mà nó muốn. Bây giờ hãy tưởng tượng đó filelà một tệp nhật ký 100 GB ...
bay xốp vào

7
@styrofoamfly: Chính xác là less <filegiữ tất cả các tệp trong bộ nhớ, nhưng nó không bị ép buộc, đây là một thiếu sót ít hơn. Chỉ cat file | lessbị buộc phải. Kiểm tra less /dev/fd/0 <f, cái mà không giữ tập tin trong bộ nhớ, mặc dù nó nhận được nó trên stdin. Đó là một quan niệm sai lầm phổ biến rằng stdin trong Unix là không thể hiểu được. Thực tế, nó có thể được tìm kiếm, tùy thuộc vào loại tệp.
pts

@styrofoamfly Bạn có nghĩa là read()đọc dữ liệu tuần tự từ một tệp, trong khi mmap()đọc toàn bộ tệp vào bộ nhớ cùng một lúc?
Tim

1
@JohnBollinger Không. Nó bắt nguồn từ ít nhất là từ getyst từ SysIII vào năm 1980 trước khi dự án GNU được bắt đầu và được yêu cầu hỗ trợ cho hầu hết các tiện ích tiêu chuẩn bao gồm cả sortPOSIX. Nhưng sự thật là không phải lúc nào nó cũng được hỗ trợ.
Stéphane Chazelas

2
Tôi xin lỗi, @ StéphaneChazelas, bạn đã đúng về nguồn gốc của quy ước và tôi cũng sẽ quy định thêm rằng đặc tả POSIX cho getopt()hàm C nhận ra ý nghĩa này của đối số --. Nhưng điểm chính là vấn đề mà bạn chấp nhận: xử lý đối số là miền của các chương trình riêng lẻ và không phải tất cả đều được đối xử --đặc biệt.
John Bollinger

17

Vấn đề là tên tệp bắt đầu bằng dấu gạch ngang. sort "$f1"không hoạt động nếu giá trị f1bắt đầu bằng -vì lệnh sẽ diễn giải giá trị dưới dạng tùy chọn. Điều này thường dẫn đến một lỗi nhưng nó thậm chí có thể gây ra lỗ hổng bảo mật . Với sort -- "$f1", đối số dấu gạch ngang kép --có nghĩa là không có tùy chọn nào ngoài điểm này, vì vậy giá trị của f1sẽ không được hiểu là một tùy chọn. Nhưng vẫn còn một trường hợp cạnh: nếu giá trị của f1là một dấu gạch ngang và không có gì khác, thì đó không phải là một tùy chọn, đó là đối số -, có nghĩa là đầu vào tiêu chuẩn, (vì đối số là một tệp đầu vào; nó có nghĩa là đầu ra tiêu chuẩn của người dùng).

Sử dụng chuyển hướng tránh tất cả những cạm bẫy.

Điều này áp dụng cho hầu hết các lệnh, không chỉ sort.


Bạn đang nói rằng sort < "$f1"sẽ làm việc nếu giá trị bằng -? Nó không có trong bất kỳ vỏ tôi đã thử.
grawity

@grawity, so sánh seq 10 > -; sort -với seq 10 > -; sort < -.
Stéphane Chazelas
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.