Un programma che potrebbe bufferizzare lo stdin o il file


12

A parte l'utilizzo di un file temporaneo per aiutare, c'è un modo / programma che può bufferizzare l'input stdinma non emette il contenuto fino a quando non ottiene il file EOF. Non voglio nemmeno usare una variabile di shell (ad es buffer=$(cat).).

Questo programma dovrebbe funzionare come di seguito (supponiamo che il nome del programma sia buffered-cat):

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

Ora che il programma ha ricevuto ^D, buffered-cati contenuti vengono emessi

line 1
line 2
line 3

Di solito lo uso sortper questo scopo. Ovviamente ha effetti collaterali che potrebbero essere indesiderati.
Adrian Pronk il

Risposte:


20

Un povero sta spongeusando awk:

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

Se lo hai tac, puoi anche abusarne:

... | tac | tac

1
tacè semplice ed elegante, penso.
Ekeyme Mo

6
@EkeymeMo | tac | tac è semplice, ma tieni presente che è altamente inefficiente per l'attività e subirai un calo delle prestazioni, specialmente per file più grandi.
Trauma digitale

@DigitalTrauma sì, ne conosco lo svantaggio. Provo un file che con 100 mila righe. Va bene per me. Ho votato il tuo commento perché è vero.
Ekeyme Mo

29

Puoi farlo con spongemoreutils .sponge"assorbirà l'input standard e scriverà in un file". Senza argomenti, quel file è un output standard. Gli input dati a questo comando vengono archiviati in memoria fino a EOF, quindi scritti tutti in una volta.

Per scrivere su un file normale, puoi semplicemente dare il nome del file:

cmd | sponge filename

Lo scopo principale di spongeè consentire la lettura e la scrittura dallo stesso file all'interno di una pipeline, ma fa anche quello che vuoi.


6

Finché il tuo input è il testo ASCII (non contiene NUL 0x0 byte fino alla fine), quindi sed -zfa quello che vuoi:

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

Le -zcause sedper trattare il byte NUL come un delimitatore di linea anziché la solita newline. Quindi fino a quando l'input è un testo normale senza byte NUL, sed continuerà a leggere l'intero input nel suo buffer di pattern fino al raggiungimento di EOF. sedquindi non esegue alcuna elaborazione sul buffer e lo emette.


Se nel tuo input sono presenti byte NUL, puoi invece farlo:

sed ':l;N;bl'

4

Questa sedsoluzione è leggermente più lunga di quella di DigitalTrauma, ma funziona anche con byte NUL.

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

2
sed ':l;N;bl'dovrebbe funzionare anche.
Trauma digitale

1

Il comportamento che stai chiedendo, non è il comportamento predefinito di un gatto semplice?

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
No, questo è il comportamento dei documenti qui. Prova a digitare cat(Invio) Line 1(Invio) e guarda cosa succede.
G-Man dice "Ripristina Monica" il

Sì, questa è la struttura qui-doc. Semplice e molto vicino a ciò che vuole OP.
Neanche

1

Stessa idea dell'esempio imbarazzante di Muru, tranne in Python. Utilizzare CtrlDper interrompere la lettura in righe

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

3
Oppure perl -e 'print <>'(!)
dave_thompson_085,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.