Програма, яка може буферувати stdin або файл


12

Окрім використання тимчасового файлу для допомоги, чи існує спосіб / програма може буферизувати вхід, stdinале не виводити вміст до отримання EOF. Я також не хочу використовувати змінну оболонки (наприклад buffer=$(cat)).

Ця програма повинна поводитись як показано нижче (припустимо, назва програми buffered-cat):

$ buffered-cat
line 1
line 2
line 3
^D # Ctr-D here(End of Line)

Тепер, коли програма отримала ^D, buffered-catвиводить вміст

line 1
line 2
line 3

Я зазвичай використовую sortдля цієї мети. Очевидно, що він має побічні ефекти, які можуть бути небажаними.
Адріан Пронк

Відповіді:


20

Бідний чоловік spongeвикористовує awk:

awk '{a[NR] = $0} END {for (i = 1; i <= NR; i++) print a[i]}'

Якщо у вас є tac, ви також можете зловживати ним:

... | tac | tac

1
tacце просто і елегантно, я думаю.
Екімей Мо

6
@EkeymeMo | tac | tac є простим, але майте на увазі , що це вкрай неефективно для виконання цього завдання , і ви будете страждати від втрати продуктивності, особливо для великих файлів.
Цифрова травма

@DigitalTrauma Так, я знаю недолік цього. Я перевіряю файл, який має 100 тисяч рядків. Для мене це нормально. Я проголосував за ваш коментар, як це правда.
Ekeyme Mo

29

Це можна зробити за spongeдопомогою Moreutils . spongeбуде "вбирати стандартний вхід і записувати у файл". Без аргументів цей файл є стандартним висновком. Введені дані команди зберігаються в пам'яті до EOF, а потім виписуються всі відразу.

Для запису до звичайного файлу ви можете просто вказати ім'я файлу:

cmd | sponge filename

Основна мета sponge- дозволити читати і записувати з того самого файлу в конвеєрі, але він також робить те, що ви хочете.


6

Поки ваш текст - це текст ASCII (не містить NUL 0x0 байт до кінця), то виконайте sed -zте, що вам потрібно:

$ sed -z ''
Line 1
Line 2
Line 3
^D
Line 1
Line 2
Line 3
$ 

У -zпричинах sedдля лікування NUL байт в якості роздільника рядка замість звичайної рядка. Так що, поки ваш вхід є звичайним текстом без байтів NUL, тоді sed продовжуватиме читати весь вхід у його буфер візерунка, поки не буде досягнуто EOF. sedпотім не здійснює обробку в буфері і виводить його.


Якщо у вашому вкладі присутні байти NUL, ви можете зробити це замість цього:

sed ':l;N;bl'

4

Це sedрішення трохи довше, ніж DigitalTrauma, але також працює з байтами NUL.

sed -n 'H;${x;s/^\n//;p}'

2
sed ':l;N;bl'також повинен працювати.
Цифрова травма

1

Поведінка, про яку ви просите, чи не поведінка простої кішки за замовчуванням?

gv@debian:$ cat << EOF #or cat <<EOF >file or cat <<EOF >/dev/stdout
> Line 1
> Line 2
> Line 3
> EOF
Line 1
Line 2
Line 3
gv@debian:$

3
Ні, така поведінка тут документів. Спробуйте ввести cat(Enter) Line 1(Enter) і подивіться, що відбувається.
G-Man каже: "Відновіть Моніку"

Так, це структура тут. Простий і дуже близький до того, що хоче ОП. Також не потрібна установка
Сергій Колодяжний

1

Та сама ідея, що і у Муру дивним прикладом, за винятком Python. Використовуйте CtrlDдля зупинки читання в рядках

$ python -c 'import sys;print("".join(sys.stdin.readlines()))'                                                           
line1
line2
line3 # press Enter and Ctrl+D at this point
line1
line2
line3

3
Або perl -e 'print <>'(!)
dave_thompson_085
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.