2010-04-04 7 views
3

Je suis en train de faire quelque chose comme çaSource de Standard In (Bash sur OSX)

ruby test.rb | source /dev/stdin 

où test.rb qu'afficher sur cd /. Il n'y a pas d'erreurs, mais ça ne fait rien non plus. Si j'utilise ceci:

ruby test.rb > /tmp/eraseme2352; source /tmp/eraseme2352 

cela fonctionne très bien, mais je veux éviter le fichier intermédiaire.

Editer: Le but de tout cela est que les changements doivent persister lorsque la commande est terminée. Désolé, je n'ai pas précisé cela plus tôt.

+0

Votre première commande 'fonctionne'; le problème est que le pipeline s'exécute dans une sous-shell, de sorte que le sous-shell source la sortie de ruby, puis se termine, laissant le processus parent inchangé. C'est pourquoi le fichier temporaire explicite fonctionne comme vous le souhaitez. Recherchez «Substitution de processus» (§ 3.5.6 dans le manuel 4.0 Bash) et voyez si vous pouvez utiliser: 'source <(ruby test.rb)'. –

+0

Empiriquement, ça ne marche pas: ça fonctionne aussi dans une sous-shell, je suppose. –

+0

Ne fonctionne pas - parce que vous obtenez 'sh: erreur de syntaxe près d'un jeton inattendu '(''? C'est ce que j'ai obtenu sur Snow Leopard avec 'sh' comme shell, mais ça marche bien si j'utilise bash au lieu de sh Si j'essaie 'cat <(echo abc)' j'obtiens le résultat attendu (une ligne de sortie avec 'ab c'). Si j'essaie 'source' ou '.' À la place, il semble être ignoré - ce que je prendre pour être équivalent à "il forge et exécute la commande et le sous-shell fait la source et puis sort" .Un essai, mais pas la réponse.Il semble que vous aurez à faire le travail de longue main , vous souvenant d'effacer le fichier eraseme dès que possible –

Répondre

6

Vous pouvez essayer:

$(ruby test.rb) 

$(...) dit bash pour exécuter ce que la sortie est produit par commande à l'intérieur ().

+0

Cela berce et résout des tas de problèmes. –

+0

Pendant que nous sommes ici: est-il possible de faire en sorte que le shell ne montre PAS les commandes pendant leur exécution? –

+1

Attention, cela ne fonctionne que si le script Ruby affiche une seule ligne de commande. Si elle crache plusieurs lignes, elles seront toutes réunies en une seule grande commande. – Thomas

0

Que diriez-vous juste

ruby test.rb | bash 
+1

Cela va exécuter les commandes dans un sous-shell. Tous les effets secondaires tels que la modification de répertoires ou la définition de variables d'environnement seront perdus. – Thomas

+0

En effet, il le fera. Le fait de ne pas utiliser de sous-shell ne figurait pas exactement dans la liste des exigences ... la syntaxe $() semble bien plus agréable. –

+1

C'est un peu implicite comme une exigence étant donné le code d'exemple. –

2

Jusqu'à ce qu'un plus hacker bash expérimenté vient de me corriger, vous pouvez le faire:

for c in `ruby test.rb` ; do $c ; done 

Attention: Cela ne fait pas ce que vous voulez . Lisez les commentaires!

+0

Cela pourrait aussi être utile. Merci. –

+0

Ceci traitera chaque 'mot' (jetons séparés vierges) dans la sortie du script Ruby comme une commande. Si aucune commande n'a d'arguments, cela fonctionnera. Si une commande a des arguments, cela ne fonctionnera pas. –

+0

Le problème est que c'est le problème que j'essaie d'éviter: apprendre les scripts shell. Y a-t-il un moyen pour moi de formater ma sortie afin de la faire fonctionner sur plusieurs lignes? Ce que je veux vraiment faire c'est '| source: –

3
eval `ruby test.rb` 
+0

Pourquoi auriez-vous besoin du 'eval'? – Thomas

+1

@Thomas: parce que, par exemple, 'eval $ (echo 'var1 = 27; var2 = 38')' fonctionne comme prévu définit ces variables dans le shell actuel. Sans le 'eval', il est exécuté comme une commande et donne une erreur:" var1 = 27; var2 = 38: commande non trouvée ". –

+0

L'intrigue s'épaissit, cool! –

1

bash (non sh):

while read -a line 
do 
    "${line[@]}" 
done < <(somescript) 

espaces dans des arguments aux commandes devra être pour travailler échappé backslash.

+0

bien, merci, mais je pense que je pourrais aller avec 'eval $()' comme meilleure réponse. –

2

Le code suivant fonctionne pour moi sur Mac OS X 10.6.7:

/bin/bash 

sw_vers # Mac OS X 10.6.7 

bash --version # GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin10.0) 

source /dev/stdin <<<'echo a b c' 

source /dev/stdin <<< "$(ruby -e 'puts "echo a b c"')" 

source /dev/stdin <<<'testvar=TestVal'; echo $testvar 


source /dev/stdin <<-'EOF' 
echo a b c 
EOF 

source /dev/stdin <<-'EOF' 
$(ruby -e 'puts "echo a b c"') 
EOF 

(
source /dev/stdin <<-'EOF' 
testvar=TestVal 
EOF 
echo $testvar 
)