2009-09-28 30 views
5

Ho un programma che legge dallo standard input quando viene richiamato dalla riga di comando. Normalmente l'utente dovrebbe inserire alcune informazioni, premere C-d su una nuova riga per segnalare la fine del file e il programma elaborerebbe il file. Quindi l'utente verrebbe nuovamente richiesto, inserirebbe un altro testo e premere nuovamente C-d per segnalare la fine del secondo file.invio di più file dallo script della shell tramite l'input standard

Sto cercando di scrivere uno script di shell che invocherà questo programma e invierà automaticamente i due file. Mi piacerebbe fare qualcosa di simile:

$ myprogram < file1.txt < file2.txt 

O

$ myprogam <file1.txt file2.txt 

Qualche suggerimento? Sto usando la shell bash sotto Linux.

+0

Come indica la fine di tutti i file? Due controlli-D di fila? Il design standard per i programmi Unix è "leggere i file indicati sulla riga di comando, se non ci sono file di questo tipo, elaborare lo standard input". Se si adotta questo design, non ci sono problemi; invochi semplicemente "myprogram file1.txt file2.txt". –

risposta

0

Una cosa probabile da fare sarebbe utilizzare expect.

3

Ovviamente è possibile utilizzare cat di inviare due file in ingresso standard programmi, ma questo non è probabilmente quello che volete:

$ cat file1.txt file2.txt | myprogram 

Nel caso di cui sopra myprogram non sarebbe in grado di dire dove finisce file1.txt e file2.txt inizia, a meno che non avessero una formattazione specifica e stava guardando lo stream per una determinata formattazione che indicava la fine o l'inizio di un file.

Non esiste un modo standard per l'invio di più flussi nell'input standard. Essenzialmente, c'è solo un singolo flusso che entra nello standard input.

Probabilmente dovresti strutturare lo script in modo che accettasse più argomenti sulla riga di comando e li avessi aperti e elaborati internamente uno alla volta. Cioè, si chiama in questo modo:

$ myprogram file1.txt file2.txt 
+0

forse c'è un modo per dire: $ cat file1.txt "EOF" file2.txt e quindi saprebbe che sono due file separati? –

+0

No, non esiste un modo per inviare EOF in questo modo; guarda i miei commenti alla risposta di Pavel Shved. –

0

Jonathan Leffler dice nel suo commento, che la mia soluzione non è corretta. Forse lo è. In realtà non l'ho controllato a fondo. Ma lascia che sia qui solo per informazioni che è una risposta sbagliata, almeno.


Bash può richiamare un carattere di controllo con il suo comando echo. EOF è C-d, come hai già notato, quindi cerchiamo di utilizzare un subshell:

$ (cat file1.txt ; echo -e '\cD' ; cat file2.txt) | myprogram 

Ciò eseguire comandi all'interno delle parentesi e il tubo di uscita di tutti loro, come se si trattasse di un programma separato.

Se non si è sicuri che i tubi in modo corretto, provare questo:

$ (echo "Hello" ; echo -e '\cD' ; echo "bash") | tee 
+1

Il controllo-D viene intercettato dal driver del terminale e lo fa inviare tutti i dati in sospeso - nessun carattere se non ce ne sono in sospeso. Il programma ottiene quindi una lettura a zero byte, che indica EOF. Il controllo letterale dei caratteri di controllo-D in fondo alla pipeline non simula questo: non c'è un driver del terminale che assista. Ecco dove arriva "expect" - utilizza pseudo-tty per emulare i terminali. –

2

ha a che essere 1 invocazione? In caso contrario:

for file in file1 file2 file3; do myprogram < $file; done 
0

Ho scritto un semplice programma Python per simulare il comportamento del programma che descrivi. Al minimo, questo ci mette tutti nella posizione di parlare della stessa cosa invece di assumere come funziona il tuo programma. (Naturalmente, se il tuo programma non funziona nel modo in cui lo sto descrivendo qui, per favore correggimi.)

#!/usr/bin/python 

def read_a_file(): 
    print('Type the contents of a file now.') 
    while True: 
     try: 
      s = raw_input('>') 
     except EOFError: 
      break 

read_a_file() 
read_a_file() 
print('We have now read two files. Quitting.') 

È possibile eseguire questo script, digitare il contenuto del primo file, premere Ctrl-D, digitare il contenuto del secondo file, premere CTRL-D, e il programma termina. Questo sembra essere il comportamento che stai descrivendo.

Il mio primo pensiero è stato quello di aspettarmi, come suggerito dal caos. Tuttavia, non riesco a trovare alcun supporto in attesa di piping il contenuto di un file in un processo. (Suppongo che il contenuto dei file sia diverso ogni volta. Se sono uguali, allora aspettarsi funzionerebbe, semplicemente inserendo il contenuto dei file nello script expect.)

Devo notare che sono in nessun modo un esperto prevedi; potrebbe esserci un modo per farlo che non è ovvio per me.

Il mio secondo pensiero è stato quello di scrivere uno script Python che ha lanciato il tuo programma, e alimentato il contenuto dei file e dei caratteri EOF. Tuttavia, i commenti di Jonathan Leffler mi hanno fatto pensare che l'eco dei personaggi EOF non avrebbe funzionato.

Il mio terzo pensiero è davvero dannatamente triste. È possibile scrivere uno script che crei uno script previsto collegando il contenuto dei file allo script expect e quindi eseguendo lo script expect. Sospetto che funzionerebbe.

Problemi correlati