Un programa que podría almacenar el stdin o el archivo

12

Además de usar un archivo temporal para ayudar, ¿hay alguna forma en que el programa pueda almacenar la entrada de la memoria intermedia stdinpero no la envíe hasta que obtenga el contenido EOF? Tampoco quiero usar una variable de shell (por ejemplo buffer=$(cat)).

Este programa debe comportarse de la siguiente manera (suponga que el nombre del programa es buffered-cat):

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

Ahora que recibió el programa ^D, buffered-catel contenido sale

line 1
line 2
line 3
Ekeyme Mo
fuente
Normalmente lo uso sortpara este propósito. Obviamente tiene efectos secundarios que pueden ser indeseables.
Adrian Pronk

Respuestas:

20

El pobre spongeusa awk:

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

Si es así tac, también puedes usarlo mal:

... | tac | tac
muru
fuente
1
tacEs simple y elegante, creo.
Ekeyme Mo
66
@EkeymeMo | tac | tac es simple, pero tenga en cuenta que es muy ineficiente para la tarea y sufrirá un impacto en el rendimiento, especialmente para archivos más grandes.
Trauma digital
@ DigitalTrauma, sí, conozco el inconveniente de eso. Pruebo un archivo que tiene 100 mil líneas. Esta bien para mi. He votado tu comentario porque es verdad.
Ekeyme Mo
29

Puede hacerlo con spongemoreutils . sponge"absorberá la entrada estándar y escribirá en un archivo". Sin argumentos, ese archivo es salida estándar. La entrada dada a este comando se almacena en la memoria hasta EOF, y luego se escribe de una vez.

Para escribir en un archivo normal, solo puede dar el nombre de archivo:

cmd | sponge filename

El propósito principal de spongees permitir leer y escribir desde el mismo archivo dentro de una tubería, pero también hace lo que quiere.

Michael Homer
fuente
6

Siempre que su entrada sea texto ASCII (no contiene NUL 0x0 bytes hasta el final), entonces sed -zhace lo que desea:

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

Las -zcausas sedpara tratar el byte NUL como un delimitador de línea en lugar de la nueva línea habitual. Entonces, siempre que su entrada sea texto normal sin bytes NUL, entonces sed continuará leyendo toda la entrada en su búfer de patrón hasta que se alcance EOF. sedluego no procesa en el búfer y lo genera.


Si hay bytes NUL en su entrada, puede hacer esto en su lugar:

sed ':l;N;bl'
Trauma digital
fuente
4

Esta sedsolución es un poco más larga que la de DigitalTrauma, pero también funciona con bytes NUL.

sed -n 'H;${x;s/^\n//;p}'
JoL
fuente
2
sed ':l;N;bl'debería funcionar también.
Trauma digital
1

El comportamiento que está solicitando, ¿no es el comportamiento predeterminado de un gato simple?

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:$
George Vasiliou
fuente
3
No, ese es el comportamiento de los documentos aquí. Intente escribir cat(Enter) Line 1(Enter) y vea qué sucede.
G-Man dice 'reinstalar a Monica' el
Sí, esa es la estructura del documento aquí. Simple y se acerca bastante a lo que OP quiere. Tampoco requiere instalación
Sergiy Kolodyazhnyy
1

La misma idea que el ejemplo awk de muru, excepto en Python. Use CtrlDpara dejar de leer en líneas

$ python -c 'import sys;print("".join(sys.stdin.readlines()))'                                                           
line1
line2
line3 # press Enter and Ctrl+D at this point
line1
line2
line3
Sergiy Kolodyazhnyy
fuente
3
O perl -e 'print <>'(!)
dave_thompson_085