Lệnh shell sau đây dự kiến chỉ in các dòng lẻ của luồng đầu vào:
echo -e "aaa\nbbb\nccc\nddd\n" | (while true; do head -n 1; head -n 1 >/dev/null; done)
Nhưng thay vào đó, nó chỉ in dòng đầu tiên : aaa
.
Điều tương tự không xảy ra khi nó được sử dụng với tùy chọn -c
( --bytes
):
echo 12345678901234567890 | (while true; do head -c 5; head -c 5 >/dev/null; done)
Lệnh này xuất ra 1234512345
như mong đợi. Nhưng điều này chỉ hoạt động trong việc triển khai coreutils của head
tiện ích. Việc thực hiện busybox vẫn ăn thêm các ký tự, vì vậy đầu ra chỉ là 12345
.
Tôi đoán cách thực hiện cụ thể này được thực hiện cho mục đích tối ưu hóa. Bạn không thể biết dòng kết thúc ở đâu, vì vậy bạn không biết bạn cần đọc bao nhiêu ký tự. Cách duy nhất để không tiêu thụ thêm ký tự từ luồng đầu vào là đọc byte luồng theo byte. Nhưng đọc từ luồng một byte mỗi lần có thể chậm. Vì vậy, tôi đoán head
đọc luồng đầu vào vào một bộ đệm đủ lớn và sau đó đếm các dòng trong bộ đệm đó.
Điều tương tự không thể được nói cho trường hợp khi --bytes
tùy chọn được sử dụng. Trong trường hợp này, bạn biết bạn cần đọc bao nhiêu byte. Vì vậy, bạn có thể đọc chính xác số byte này và không nhiều hơn thế. Việc triển khai corelibs sử dụng cơ hội này, nhưng busybox thì không, nó vẫn đọc nhiều byte hơn mức cần thiết vào bộ đệm. Nó có thể được thực hiện để đơn giản hóa việc thực hiện.
Vì vậy, câu hỏi. Có đúng không khi head
tiện ích tiêu thụ nhiều ký tự từ luồng đầu vào hơn so với yêu cầu? Có một số loại tiêu chuẩn cho các tiện ích Unix? Và nếu có, nó có chỉ định hành vi này không?
PS
Bạn phải nhấn Ctrl+C
để dừng các lệnh trên. Các tiện ích Unix không thất bại khi đọc xa hơn EOF
. Nếu bạn không muốn nhấn, bạn có thể sử dụng một lệnh phức tạp hơn:
echo 12345678901234567890 | (while true; do head -c 5; head -c 5 | [ `wc -c` -eq 0 ] && break >/dev/null; done)
mà tôi đã không sử dụng cho đơn giản.