Automatizzare l'input testuale da uno script bash senza usare EOF


10

Sto eseguendo Ubuntu Linux. Supponiamo che esista un programma chiamato myprogram. Questo programma richiede all'utente l'input; in particolare, l'utente deve digitare un numero intero quando richiesto e premere Enter. Vorrei automatizzare questo processo usando uno script bash. In particolare, vorrei eseguire myprogram, diciamo, 100 volte (usando un contatore iche va da 1a 100). Ad ogni esecuzione di myprogram, vorrei inserire il valore corrente di iquando richiesto.

(A proposito, myprogramaccetta opzioni / opzioni -options, tutte che saranno costanti e quindi specificate nello script bash.)

Uno scheletro incompleto di questo script bash potrebbe essere:

#!/bin/bash
for i in {1..100}
do
   myprogram -options
done

Ora vorrei modificare il codice sopra in modo che il valore corrente di isia inserito quando richiesto dal programma. Qual è il modo migliore per farlo?

Il sito Web del software che sto utilizzando suggerisce di utilizzare <<EOFalla fine della myprogram -optionsriga. Penso che questo dice a bash di guardare alla "fine del file" per l'input da usare. E se non volessi inserire l'input alla fine del file? E se volessi metterlo immediatamente dopo il <<o <?

Il motivo è che le cose diventeranno più complicate. Ad esempio, posso introdurre un contatore di numeri interi jche cambia in modo non lineare e non sequenziale. Vorrei quindi alimentare il valore corrente di ja myprogramsu ogni iterazione, ma il valore di jpuò cambiare tra la chiamata a myprogram -optionse la fine del file EOF.

Hai qualche suggerimento?


Controlla questo blog - Esecuzione di programmi interattivi
Suresh

Risposte:


14

Per quasi tutti i programmi, entrambi echo $i | myprogram -optionse myprogram -options <<<$idovrebbero funzionare, alimentando il programma $itramite input standard.

<fooutilizzerà il contenuto del file denominato foocome stdin.

<<fooutilizzerà il testo tra questo e una riga costituita esclusivamente fooda input standard. Questo è un documento qui (ereditario), come diceva Gilles; EOFin realtà non significa la fine del file, è solo un delineatore ereditario comune (in questo esempio usiamo "pippo").

<<<fooutilizzerà la stringa "pippo" come input standard. Puoi anche specificare una variabile $fooe la shell utilizzerà il suo contenuto come stdin, come ho mostrato sopra. Questo si chiama herestring , poiché usa una stringa corta in contrasto con un intero blocco, come in una eredità. Herestrings funziona in bash, ma non in /bin/sh.


9

La sintassi consigliata da questo sito Web si chiama qui documento . L'input per il programma di file inizia immediatamente sotto la riga che contiene <<EOFe non termina alla fine dello script, ma da una riga che contiene esattamente il testo EOF(fare attenzione a non avere spazi bianchi extra). A proposito, puoi usare qualsiasi marcatore finale che non contenga alcun carattere speciale di shell: EOFnon è una parola chiave, è semplicemente tradizionale.

#!/bin/bash
for i in {1..100}
do
   myprogram -options <<EOF
$i
EOF
   for j in {1..42}; do
     myprogram2 <<EOF
$i
$j
EOF
   done
done

in altre parole, EOF in questo contesto indica un marcatore di fine file , non la fine effettiva del file di script. il testo "EOF" è qualsiasi testo arbitrario - qualunque cosa tu usi immediatamente dopo i caratteri << indicherà la fine del documento qui-ora. In genere uso EOF perché si distingue ed è molto improbabile che sia all'interno del documento Herenow se, ad esempio, sto generando programmaticamente lo script della shell (cosa che faccio abbastanza spesso).
Cas

che il grassetto EOF dovrebbe essere <underscore><underscore>EOF<underscore> <underscore>
cas

Usando documenti come questo, ho spesso cambiato il marcatore finale in qualcosa di molto più significativo (e meno probabile che corrisponda "casualmente"), come END_OF_WHATEVER_FUNCTION. A volte, cercare di "salvare" spazio / dimensioni è in realtà uno spreco di sforzi perché provoca ambiguità su ciò che sta realmente accadendo.
assassino l'

Come è possibile sleeptra i comandi leggere dallo script?
boltup_im_coding

@ unexpected62 Non capisco cosa stai chiedendo. Probabilmente dovresti porre una nuova domanda su questo sito. Assicurati di dare abbastanza contesto.
Gilles 'SO-smetti di essere malvagio'

3

qui i documenti citati sia da Kevin che da Gilles sopra, o la semplice tubatura funzionerà in molti casi.

Per situazioni più complicate, potresti voler esaminare Expect o simili (ad esempio il modulo Expect :: Simple CPAN è un'implementazione perl molto facile da usare). personalmente, preferisco il modulo perl (Expect stesso è tcl) ma ci sono implementazioni per molti linguaggi di scripting comuni. È anche possibile scrivere un'implementazione molto primitiva dell'idea in sh o bash usando while e read.

L'idea generale di Expect e strumenti simili è di attendere una stringa o un modello specificati nell'output di un programma e quindi alimentarlo con qualsiasi input desiderato.

Un esempio comune è quello di automatizzare l'accesso, "aspettandosi" (cioè aspettando) la stringa "ogin:", inviare il nome di accesso, quindi aspettarsi la stringa "parola:" e inviare la password.

Un'ultima opzione, se hai la fonte di myprogram, è semplicemente modificarla per prendere l'input che vuoi dare come opzione da riga di comando. Questo potrebbe essere un po 'più impegnativo in anticipo, ma sarà molto meno aggravante del pasticciare con Expect o il piping dei dati in un programma che non è stato progettato per essere utilizzato in quel modo.

... e non dimenticare di inviare la tua patch per riprogrammare a monte :) Anche se non gli piace il modo in cui l'hai codificata, potrebbe piacere l'idea abbastanza da aggiungere la funzione da soli. Gli sviluppatori a monte tendono ad apprezzare le persone che escono dal culo e contribuiscono piuttosto che chiedere o lamentarsi.

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.