Un programme qui pourrait mettre en mémoire tampon stdin ou fichier

12

Mis à part l'utilisation d'un fichier temporaire pour aider, y a-t-il un moyen / programme pourrait tamponner l'entrée à partir de stdinmais ne sort pas le contenu jusqu'à ce qu'il obtienne le EOF. Je ne veux pas non plus utiliser de variable shell (par exemple buffer=$(cat)).

Ce programme doit se comporter comme ci-dessous (en supposant que le nom du programme est buffered-cat):

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

Maintenant que le programme a été reçu ^D, buffered-catle contenu sort

line 1
line 2
line 3
Ekeyme Mo
la source
J'utilise normalement sortà cet effet. De toute évidence, il a des effets secondaires qui peuvent être indésirables.
Adrian Pronk

Réponses:

20

Un pauvre spongeutilise awk:

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

Si c'est le cas tac, vous pouvez également en abuser:

... | tac | tac
muru
la source
1
tacest simple et élégant, je pense.
Ekeyme Mo
6
@EkeymeMo | tac | tac est simple, mais gardez à l'esprit qu'il est très inefficace pour la tâche et vous souffrirez d'un impact sur les performances, en particulier pour les fichiers plus volumineux.
Digital Trauma
@DigitalTrauma ouais, je connais l'inconvénient de cela. Je teste un fichier avec 100 000 lignes. C'est bon pour moi. J'ai voté pour votre commentaire car il est vrai.
Ekeyme Mo
29

Vous pouvez le faire avec spongemoreutils . sponge"absorbera l'entrée standard et écrit dans un fichier". Sans argument, ce fichier est une sortie standard. L'entrée donnée à cette commande est stockée en mémoire jusqu'à EOF, puis écrite en une seule fois.

Pour écrire dans un fichier normal, vous pouvez simplement donner le nom du fichier:

cmd | sponge filename

Le but principal de spongeest de permettre la lecture et l'écriture à partir du même fichier dans un pipeline, mais il fait aussi ce que vous voulez.

Michael Homer
la source
6

Tant que votre entrée est du texte ASCII (ne contient aucun octet NUL 0x0 jusqu'à la fin), sed -zfait ce que vous voulez:

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

Les -zcauses sedde traiter l'octet NUL comme un délimiteur de ligne au lieu de la nouvelle ligne habituelle. Donc, tant que votre entrée est du texte normal sans octets NUL, sed continuera de lire l'intégralité de l'entrée dans son tampon de modèle jusqu'à ce que EOF soit atteint. sedne fait alors aucun traitement sur le tampon et le sort.


Si des octets NUL sont présents dans votre entrée, vous pouvez le faire à la place:

sed ':l;N;bl'
Traumatisme numérique
la source
4

Cette sedsolution est un peu plus longue que celle de DigitalTrauma, mais fonctionne également avec des octets NUL.

sed -n 'H;${x;s/^\n//;p}'
JoL
la source
2
sed ':l;N;bl'devrait aussi fonctionner.
Digital Trauma
1

Le comportement que vous demandez, n'est-ce pas le comportement par défaut d'un simple chat?

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
la source
3
Non, c'est le comportement des documents ici. Essayez de taper cat(Entrée) Line 1(Entrée) et voyez ce qui se passe.
G-Man dit `` Réintègre Monica '' le
Oui, c'est la structure ici-doc. Simple et se rapproche assez de ce que OP veut. Ne nécessite pas d'installation non plus
Sergiy Kolodyazhnyy
1

Même idée que l'exemple awk de muru, sauf en Python. Utilisez CtrlDpour arrêter la lecture des lignes

$ 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
la source
3
Ou perl -e 'print <>'(!)
dave_thompson_085