Программа, которая может буферизовать стандартный ввод или файл


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это просто и элегантно, я думаю.
Ekeyme Mo

6
@EkeymeMo | tac | tac является простым, но имейте в виду , что это крайне неэффективно для выполнения этой задачи , и вы будете страдать от потери производительности, особенно для больших файлов.
Цифровая травма

@DigitalTrauma да, я знаю недостаток этого. Я тестирую файл со 100 тысячами строк. Это хорошо для меня. Я проголосовал за ваш комментарий, так как это правда.
Ekeyme Mo

29

Вы можете сделать это с помощью spongemoreutils . 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 говорит «Восстановить Монику»

Да, это здесь - структура документа. Просто и довольно близко к тому, что хочет OP. Не требует установки
Сергей Колодяжный

1

Та же идея, что и в примере с muk's awk, за исключением 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

2
Или perl -e 'print <>'(!)
dave_thompson_085
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.