Passa il testo al programma in attesa di un file


30

In relazione a una domanda che ho posto su Stack Overflow: passare più righe di codice a wsadmin.sh? .

Ho, come stringa, alcune righe di input che devo inserire in un comando. Il comando, tuttavia, accetta solo un file pieno di input.

C'è un modo in cui potrei archiviare le righe in un file o pipe temporaneo che non viene mai effettivamente scritto su disco e quindi inserirlo direttamente nel programma?

Come posso fare per acquisire la pipa, alimentare l'ingresso in essa, passare quella pipa al comando e quindi liberarmi della pipa?


2
Puoi aggiungere un esempio del comando che stai usando e come dovrebbe essere invocato?
Breakthrough

2
Ciò significa che il programma non accetta stdin?
Léo Lam,

Sono d'accordo con entrambi i commentatori sopra. È impossibile suggerire qualsiasi cosa possa funzionare senza conoscere le specifiche del programma.
Larssend,

Risposte:


27

Un'altra soluzione è utilizzare la sostituzione di processo in Bash. Se il tuo sistema ha named pipe, puoi usare questa funzione.

Si usa così:

program_expecting_a_file <(list)

dove si listtrova una sequenza di comandi shell (in realtà pipeline; i dettagli completi sono qui ). listverrà eseguito e la sua uscita sarà collegata al tubo. Il nome della pipe viene quindi passato al tuo programma.

NOTA: gli spazi non sono ammessi tra <e (.

(L'altra sostituzione >(list)funziona anche come ti aspetteresti.)

Nel tuo caso specifico, potresti usare

program_expecting_a_file <(echo "$your_strings")

anche se potresti trovare la soluzione di @ meuh più elegante.

Aggiornamento: molti esempi di utilizzo sono disponibili nella Guida agli script avanzati di Bash .


Gli altri due non hanno funzionato nemmeno nei casi più banali. Il tuo ha superato i test che ho lanciato finora. Ho votato il tuo per ora. Tornerò e lo contrassegnerò come accettato se fa tutto ciò di cui ho bisogno.
ArtOfWarfare il

Il tuo funziona perfettamente. Se lo desideri, puoi aggiungerlo alla domanda correlata su StackOverflow e posso accettarlo anche lì. stackoverflow.com/questions/31374202/...
ArtOfWarfare

Ciao @ArtOfWarfare, felice di essere di aiuto. C'è già un commento laggiù con la stessa soluzione proposta, quindi non sarebbe giusto per me pubblicare una risposta lì.
Edward,

Hai pubblicato la tua soluzione prima di lui. Ad ogni modo, gli ho chiesto di cambiare il suo commento in una risposta in modo da poterlo accettare. Se nessuno di voi pubblica risposte entro ~ 24 ore su quella domanda, inserirò la risposta da solo in modo da poterla accettare (non mi piace lasciare le mie domande come senza risposta una volta trovata la risposta. È solo cattive maniere per i futuri lettori / potenziali risponditori della domanda.)
ArtOfWarfare

Ciao @ArtOfWarfare, sto benissimo con quello che proponi!
Edward,

15

Puoi usare un bash qui-doc . Per esempio,

$ cat -n <<<'a
> b'
 1  a
 2  b

Se hai qualcosa in una variabile bash puoi anche interpolarla: es <<<"path is $PATH".


Se il tuo comando insiste su un nome file, puoi assegnarlo /dev/stdin. Per esempio:

$ sed -f /dev/stdin <<<'s/a/b/'

produce l'uscita: s/b/b/.


Dalla domanda non è chiaro se il comando accetta input stdine, in caso contrario, non funzionerà. Spero che il PO chiarisca.
David Z,

1
:( - Sembrava super promettente, ma quando l'ho provato, ho ricevuto il messaggio di errore"-f" option must be followed by a file name.
ArtOfWarfare,

Un here-doc è per stdin. Se il tuo comando ha assolutamente bisogno -fe un nome file, fornisci il nome file /dev/stdin. Vedi la mia modifica.
Meuh

Penso che dopo le modifiche sia assolutamente un'opzione praticabile!
Edward,

1
+1 per il /dev/stdinsuggerimento. Il programma che sto cercando di chiamare accetta solo un nome file, quindi ho combinato /dev/stdincon un ereditario.
Huw Walters,

7

A seconda di ciò che è nel copione, si potrebbe essere in grado di utilizzare lo speciale nome del file - (meno) che sta per stdin

$ mycmd -
Line 1
Line 2
^D

Un altro metodo che potrebbe funzionare per te è aprire il file /dev/fd/0che sta di nuovo per stdin .

Una terza opzione potrebbe essere quella di creare un FIFO (First In First Out). È come un file, ma ha due estremità: scrivi ad una estremità e leggi dall'altra.

-- Process 1 --                  -- Process 2 --
$ mkfifo foo
$ cat foo
<waits>                          $ echo hello > foo
hello                            $
$ rm foo

3
Vale la pena notare che il programma deve essere scritto per interpretare in -questo modo - non è una funzionalità della shell o del sistema operativo. Sebbene, naturalmente, la maggior parte delle utility Linux standard segua questa convenzione, per quanto ne so.
David Z,

1
No. Questo non funziona per il programma. C'è una modalità interattiva, ma voglio passare i comandi per eseguire questo programma da un altro programma, e non voglio entrare nella tana del coniglio expect.
ArtOfWarfare,

@ArtOfWarfare Ho appena aggiunto una terza opzione che potrebbe funzionare.
Majenko,

Bella risposta! La seconda e la terza opzione sono sostanzialmente come la <()soluzione, ma più esplicite, il che può essere molto utile!
Edward,

4

C'è un'altra opzione simile alla mycmd -soluzione, ma anche per i programmi che non gestiscono in modo -specifico:

$ mycmd /dev/stdin
Line 1
Line 2
^D

/dev/stdin sembra essere correlato al sistema operativo e funziona per me su Debian GNU / Linux, ma non sono sicuro in quale altro luogo funzionerà.


1
Sembra che potrebbe funzionare, ma che cos'è ^D?
ArtOfWarfare il

^Dè una notazione comune per premere Ctrl-D. ^ D ha qui la semantica di "fine del flusso di input". Probabilmente è più spesso visto in ^Co ^Zche significa premere Ctrl-C rispettivamente per premere Ctrl-Z.
Axel Beckert,

1
Sembra che funzioni, ma come potrei inserire a livello di codice le cose /dev/stdine poi chiuderle?
ArtOfWarfare il

1
Basta inserire qualcosa in quel comando e dovrebbe funzionare, ad es cat content | mycmd /dev/stdin. Immagina solo comandi diversi rispetto a catqui.
Axel Beckert,
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.