Automatisation de la saisie textuelle à partir d'un script bash sans utiliser EOF

10

J'utilise Ubuntu Linux. Supposons qu'il existe un programme appelé myprogram. Ce programme invite l'utilisateur à entrer; en particulier, l'utilisateur doit saisir un entier à l'invite et appuyer sur Enter. Je voudrais automatiser ce processus en utilisant un script bash. En particulier, je voudrais exécuter myprogram, disons, 100 fois (en utilisant un compteur iqui va de 1à 100). À chaque exécution de myprogram, je voudrais saisir la valeur actuelle de ilorsque vous y êtes invité.

(Soit dit en passant, myprogramprend les options / commutateurs -options, qui seront tous constants et donc spécifiés dans le script bash.)

Un squelette incomplet de ce script bash pourrait être:

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

Maintenant, je voudrais modifier le code ci-dessus afin que la valeur actuelle de isoit entrée lorsque le programme le demande. Quelle est la meilleure façon de procéder?

Le site Web du logiciel que j'utilise suggère d' utiliser <<EOFà la fin de la myprogram -optionsligne. Je pense que cela dit à bash de regarder la "fin du fichier" pour l'entrée à utiliser. Mais que faire si je ne souhaite pas placer l'entrée à la fin du fichier? Et si j'aimerais le mettre immédiatement après le <<ou <?

La raison en est que les choses deviendront plus compliquées. Par exemple, je peux introduire un compteur entier jqui change d'une manière non linéaire et non séquentielle. Je voudrais ensuite alimenter la valeur actuelle de jto myprogramà chaque itération, mais la valeur de jpeut changer entre l'appel à myprogram -optionset la fin du fichier EOF.

Avez-vous des suggestions?

Andrew
la source
Consultez ce blog - Exécution de programmes interactifs
Suresh

Réponses:

14

Pour presque tous les programmes, à la fois echo $i | myprogram -optionset myprogram -options <<<$idevraient fonctionner, en alimentant le programme $ipar une entrée standard.

<fooutilisera le contenu du fichier nommé foostdin.

<<fooutilisera le texte entre celui-ci et une ligne composée uniquement foocomme entrée standard. C'est un document ici (heredoc), comme l'a dit Gilles; EOFne signifie pas en fait la fin du fichier, c'est juste un délimiteur hérédoc commun (nous utilisons plutôt "foo" dans cet exemple).

<<<fooutilisera la chaîne "foo" comme entrée standard. Vous pouvez également spécifier une variable $foo, et le shell utilisera son contenu comme stdin, comme je l'ai montré ci-dessus. C'est ce qu'on appelle une chaîne héréditaire , car elle utilise une chaîne courte contrairement à un bloc entier, comme dans un hérédoc. Ses chaînes fonctionnent en bash, mais pas en /bin/sh.

Kevin
la source
9

La syntaxe recommandée par ce site Web s'appelle un document ici . L'entrée dans le programme de fichiers commence immédiatement en dessous de la ligne contenant <<EOF, et elle n'est pas terminée à la fin du script, mais par une ligne contenant exactement le texte EOF(attention à ne pas avoir d'espace supplémentaire). Soit dit en passant, vous pouvez utiliser n'importe quel marqueur de fin qui ne contient aucun caractère spécial shell: EOFn'est pas un mot-clé, il est simplement traditionnel.

#!/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
Gilles 'SO- arrête d'être méchant'
la source
en d'autres termes, EOF dans ce contexte signifie un marqueur de fin de fichier , pas la fin réelle du fichier de script. le texte "EOF" est un texte arbitraire - tout ce que vous utilisez immédiatement après les caractères << indiquera la fin du document ici-maintenant. J'utilise généralement EOF car il se démarque et il est très peu probable qu'il se trouve dans le document ci-dessous si, par exemple, je génère par programmation le script shell (ce que je fais assez souvent).
cas
cet EOF en gras devrait être <underscore><underscore>EOF<underscore> <underscore>
cas
En utilisant ici des documents comme celui-ci, j'ai souvent changé le marqueur de fin en quelque chose de beaucoup plus significatif (et moins susceptible d'être apparié "au hasard"), comme END_OF_WHATEVER_FUNCTION. Parfois, essayer de «sauver» l'espace / la taille est en fait une perte d'effort car cela provoque une ambiguïté sur ce qui se passe réellement.
killermist
Comment pouvez-vous sleepentre les commandes lire le script?
boltup_im_coding
@ inattendu62 Je ne comprends pas ce que vous demandez. Vous devriez probablement poser une nouvelle question sur ce site. Assurez-vous de donner suffisamment de contexte.
Gilles 'SO- arrête d'être méchant'
3

ici, les documents mentionnés par Kevin et Gilles ci-dessus, ou la simple tuyauterie fonctionnera dans de nombreux cas.

Pour des situations plus compliquées, vous voudrez peut-être examiner Expect ou similaire (par exemple, le module Expect :: Simple CPAN est une implémentation Perl très facile à utiliser). personnellement, je préfère le module perl (Attend lui-même est tcl) mais il existe des implémentations pour de nombreux langages de script courants. Il est même possible d'écrire une implémentation très primitive de l'idée en sh ou bash en utilisant while et read.

L'idée générale d'Expect et des outils similaires est d'attendre une chaîne ou un modèle spécifié dans la sortie d'un programme, puis de l'alimenter comme vous le souhaitez.

Un exemple courant d'utilisation est d'automatiser la connexion, en «attendant» (c'est-à-dire en attendant) la chaîne «ogin:», en envoyant le nom de connexion, puis en attendant la chaîne «mot:» et en envoyant le mot de passe.

Une dernière option, si vous avez la source de myprogram, consiste simplement à le modifier pour prendre l'entrée que vous voulez lui donner comme option de ligne de commande. Cela pourrait être un peu plus de travail à l'avance, mais sera beaucoup moins aggravant que de jouer avec Expect ou de transférer des données dans un programme qui n'a pas été conçu pour être utilisé de cette façon.

... et n'oubliez pas de soumettre votre patch à myprogram en amont :) Même s'ils n'aiment pas la façon dont vous l'avez codé, ils pourraient aimer l'idée de pouvoir ajouter eux-mêmes la fonctionnalité. Les développeurs en amont ont tendance à apprécier les gens qui descendent de leurs fesses et contribuent plutôt que d'exiger ou de se plaindre.

cas
la source