/ bin / sh source de stdin (d'un autre programme) pas de fichier

14

Un peu difficile à nommer ...

Fondamentalement, j'ai un programme qui lors de l'exécution imprime sur STDOUT un ensemble de variables shell:

$ ./settings
SETTING_ONE="this is setting one"
SETTING_TWO="This is the second setting"
ANOTHER_SETTING="This is another setting".

Je veux l'exécuter à partir d'un script shell comme si le STDOUT était évalué avec source.

J'aimerais faire quelque chose comme ...

source `./settings`

... mais bien sûr, cela ne fonctionne pas.

Je sais que je pourrais faire:

./settings >/tmp/file
source /tmp/file

mais je ne veux vraiment pas faire ça.

Des indices?

Majenko
la source

Réponses:

16

Vous pouvez utiliser eval:

eval "$(./settings)"

eval "`./settings`"
Keith
la source
Désolé, j'aurais dû le mentionner, c'est / bin / sh pas bash. $ () ne fonctionne pas. J'ai mis à jour la question.
Majenko
@Matt: Eh bien, sh est bash sur la plupart des systèmes. À moins bien sûr que vous vouliez parler des versions récentes d'Ubuntu, où il a été remplacé par dash.
Hello71
@Matt: Dans ce cas, les backticks devraient fonctionner. Mais vous devriez ajouter la version exacte de shtrop - cela pourrait être un lien symbolique vers dash, ash, busybox ... Je n'ai pas vu de copie de "the real 'sh'" en direct.
user1686
1
@Matt: Vous avez donc là un ... système intéressant. D'autant plus que presque toutes les variations "sh" supportent $( )- à commencer par le shell d'Almquist dans 4.3BSD - et c'est POSIX aussi. (Remarque: ne pas discuter, juste curieux.)
user1686
$ () existe, cela ne fonctionne tout simplement pas comme ça dans cette circonstance. FreeBSD 8.2's / bin / sh
Majenko
15

Sur les systèmes où il /dev/fdest disponible, bash prend en charge la substitution de processus:

source <(./settings)

Ici, <( )s'étendra à un chemin attribué automatiquement sous /dev/fd/...lequel la sortie de ./settingspeut être lue.

user1686
la source
1
Dans le manuel bash, cela s'appelle "substitution de processus".
glenn jackman
6
declare `./settings`

Ou bien sûr ...

export `./settings`

Testez-le bien sûr ...

export `echo -e "asdf=test\nqwerty=dvorak"` ; echo $asdf $qwerty

Gestion des espaces blancs:

eval export `./settings`
Bonjour71
la source
Aha, l' exportastuce fonctionne! Merci
Majenko
Maintenant - comment gérer les espaces dans une valeur?
Majenko
@Matt: Je ne peux pas utiliser de backticks dans les commentaires, veuillez donc voir la réponse modifiée.
user1686
@grawity: Oui, vous pouvez ...a backtick --> ` <-- and here's another one --> ` <--
Hello71
2

source /dev/stdin < ./settings

Je pense que / dev / stdin est une chose Linux seulement.

LawrenceC
la source
qui essaie de trouver le contenu des paramètres. Même avec './settings', il échoue avec './settings': Ambiguous ('= backtick)
Majenko
/dev/stdinfonctionne également sur BSD et Cygwin.
user1686
1
L' utilisation |est toutefois pas aller au travail (du moins pas exactement), parce que les deux côtés du tuyau sont séparées des sous - processus, de sorte que les commandes provenant ne seraient pas affecter la coque en cours.
user1686
1
édité pour refléter cela.
LawrenceC
1
J'aime cette /dev/stdinastuce, mais ce que fait votre réponse équivaut en fait à un simple source ./settingssans l'exécuter. On pourrait utiliser un ici-document à surmonter ceci: source /dev/stdin <<EOF \n $(./settings) \n EOF.
tlwhitec
0

Je voulais apporter une autre perspective ici, car les autres réponses créent des fichiers et ne tirent pas directement de stdin. J'ai des versions qui doivent envoyer des informations d'environnement préparées à plusieurs scripts. Ce que je fais, c'est préparer un tas d'assignations de variables compatibles Bash dans une chaîne:

Var1="Foo"
Var2="Bar"
Var3="Baz"

Lorsque je me prépare à exécuter le script, j'encode en base64 la chaîne multiligne ci-dessus et la redirige dans mon script shell:

echo base64EncodedParameters | build.sh

Dans build.sh, j'ai lu depuis stdin, décodé en base64 et évalué le résultat.

params=""
while read line; do params="${params}${line}"; done
eval `echo $params | base64 -D`

echo "Hello ${Var1} ${Var2}"
Jay Proulx
la source