Tôi có thể tắt bộ đệm cho tr không


10

trdường như đệm bộ đệm đầu vào của nó để lệnh LongRunningCommand|tr \\n ,này sẽ chỉ bắt đầu tạo đầu ra sau khi một vài kilobyte đầu vào từ LongRastyCommand đã tích lũy.

Có cách nào để buộc trdừng bộ đệm này hoặc bất kỳ lệnh nào khác có thể thay thế các dòng mới bằng một nhân vật khác mà không cần đệm không?


Tái bút: Tôi đã thử hai đề xuất đầu tiên từ Tắt bộ đệm trong đường ống mà không thành công.


1
bạn đã áp dụng stdbufcho LongRastyCommand hoặc cho tr, hoặc cho cả hai, một cách khác nhau?
meuh

Để cả hai như thế này:stdbuf -o0 fping -aAq -r2 -g 10.30.0.1 10.30.0.255 2>/dev/null | stdbuf -i0 tr \\n ,
ndemou

fping -qnói "Không hiển thị kết quả trên mỗi thăm dò, mà chỉ tóm tắt cuối cùng", vì vậy có lẽ nó chỉ viết một đoạn dài ở cuối?
meuh

Không có lệnh fping hoạt động tốt của chính nó. Rất cám ơn về những lời đề nghị mặc dù
ndemou

2
Tôi nghĩ rằng vấn đề đệm thực sự là ở đầu ra của tr. Hãy thử|stdbuf -i0 -o0 tr ...
meuh

Câu trả lời:


12

Các lệnh thường không đệm đầu vào của chúng. Họ sẽ làm một read()khối lớn, nhưng khi đọc từ một đường ống, nếu không có nhiều byte trong đường ống, read()cuộc gọi hệ thống sẽ trả về với càng nhiều ký tự và ứng dụng thường hoạt động với điều đó nếu có thể .

Một ngoại lệ đáng chú ý là mawknó sẽ tiếp tục read()cho đến khi bộ đệm đầu vào đầy.

Các ứng dụng làm đệm đầu ra của chúng (stdout) mặc dù. Hành vi thông thường là nếu đầu ra sẽ ở mức tty, thì bộ đệm sẽ là dòng khôn ngoan (nghĩa là nó sẽ không bắt đầu ghi vào thiết bị xuất chuẩn cho đến khi nó có một dòng đầy đủ cho đầu ra hoặc toàn bộ khối cho dài dòng), trong khi đối với mọi loại tệp khác, bộ đệm là theo khối (nghĩa là nó sẽ không bắt đầu ghi cho đến khi có một khối đầy đủ để ghi (một cái gì đó như 4KiB / 8KiB ... phụ thuộc vào phần mềm và hệ thống )).

Vì vậy, trong trường hợp của bạn LongRunningCommandcó khả năng đệm đầu ra của nó theo các khối (vì đầu ra của nó là một đường ống chứ không phải là một tty), và trcó khả năng đệm đầu ra của nó theo dòng vì đầu ra của nó có thể là đầu cuối.

Nhưng, vì bạn loại bỏ mọi ký tự dòng mới khỏi đầu ra của nó, nó sẽ không bao giờ xuất ra một dòng, do đó, bộ đệm sẽ theo khối.

Vì vậy, ở đây bạn muốn tắt bộ đệm cho cả hai LongRunningCommandtr. Trên các hệ thống GNU hoặc FreeBSD:

stdbuf -o0 LongRunningCommand | stdbuf -o0 tr '\n' ,

Lưu ý rằng nếu bạn muốn nối các dòng bằng dấu phẩy, cách tiếp cận tốt hơn là sử dụng paste -sd , -. Bằng cách đó, đầu ra sẽ bị chấm dứt bởi một ký tự dòng mới (có thể bạn vẫn sẽ cần phải tắt bộ đệm).


@mikeerv. Có, và một cái sử dụng bộ đệm stdio và không gọi setvbuf / setbuffer ... bằng chính nó và không phải là một vỏ dựng sẵn. Nhưng nhìn chung trên các hệ thống GNU và FreeBSD, tất cả các điều kiện đó đều được thỏa mãn.
Stéphane Chazelas

Oh. Tôi chỉ biết rằng bản thân mình cách đây vài ngày khi tôi thất vọng vì tôi không thể ảnh hưởng đến các luồng i / o cho trình biên dịch tĩnh của mình sed. xin lỗi nếu nó gây phiền nhiễu - nhưng tôi không nhận ra đó là kiến ​​thức chung. tôi đoán nó sử dụng LD_PRELOAD.
mikeerv

Cảm ơn đã giải thích cặn kẽ về những gì xảy ra Stéphane. Rất cảm kích
ndemou

5

Để thay thế dòng mới ",", bạn có thể chạy

awk '{ printf "%s,", $0 }'

GNU awk ( gawk) và Solaris nawksẽ chạy với bộ đệm dòng trên stdin và không có thiết bị xuất chuẩn đệm khi đầu ra đến một thiết bị đầu cuối. Nếu awk của bạn là mawk, điều xảy ra trên Ubuntu, bạn có thể cung cấp cho nó -W interactivetùy chọn để có hành vi đệm tương tự.

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.