Je connais de deux types comment les commandes peuvent être connectées les unes aux autres:
- en utilisant un Pipe (en mettant std-output dans std-input de la commande suivante).
- en utilisant un Tee (épissez la sortie en plusieurs sorties).
Je ne sais pas si c'est tout ce qui est possible, je dessine donc un type de connexion hypothétique:
Comment pourrait-il être possible d'implémenter un flux circulaire de données entre des commandes comme par exemple dans ce pseudo code, où j'utilise des variables au lieu de commandes:
pseudo-code:
a = 1 # start condition
repeat
{
b = tripple(a)
c = sin(b)
a = c + 1
}
la source
En général, j'utiliserais un Makefile (commande make) et j'essaierais de mapper votre diagramme aux règles du makefile.
Pour avoir des commandes répétitives / cycliques, nous devons définir une politique d'itération. Avec:
chacun
make
produira une itération à la fois.la source
make
, mais inutile: si vous utilisez un fichier intermédiaire, pourquoi ne pas simplement utiliser une boucle pour le gérer?make
c'est une question de macros qui est une application parfaite ici.Vous savez, je ne suis pas convaincu que vous ayez nécessairement besoin d'une boucle de rétroaction répétitive comme le montrent vos diagrammes, autant que vous pourriez peut-être utiliser un pipeline persistant entre les coprocessus . Là encore, il se peut qu'il n'y ait pas trop de différence - une fois que vous ouvrez une ligne sur un coprocessus, vous pouvez implémenter des boucles de style typiques en écrivant et en lisant des informations sans rien faire de très inhabituel.
En premier lieu, il semblerait que ce
bc
soit un candidat de choix pour un coprocessus pour vous. Dansbc
vous pouvez desdefine
fonctions qui peuvent faire à peu près ce que vous demandez dans votre pseudocode. Par exemple, certaines fonctions très simples pour ce faire pourraient ressembler à:... qui imprimerait ...
Mais bien sûr, cela ne dure pas . Dès que le sous-shell en charge de
printf
la pipe de 's se ferme (juste après avoirprintf
écrita()\n
dans la pipe) la pipe est détruite etbc
l'entrée de' ferme 'et elle se ferme aussi. Ce n'est pas aussi utile qu'il pourrait l'être.@derobert a déjà mentionné les FIFO comme cela peut être fait en créant un fichier de canal nommé avec l'
mkfifo
utilitaire. Ce ne sont essentiellement que des canaux, sauf que le noyau système relie une entrée de système de fichiers aux deux extrémités. Celles-ci sont très utiles, mais ce serait mieux si vous pouviez simplement avoir un tuyau sans risquer qu'il soit espionné dans le système de fichiers.En fait, votre shell fait beaucoup cela. Si vous utilisez un shell qui implémente la substitution de processus, vous disposez d'un moyen très simple d'obtenir un canal durable - du type que vous pourriez attribuer à un processus en arrière-plan avec lequel vous pouvez communiquer.
Dans
bash
, par exemple, vous pouvez voir comment fonctionne la substitution de processus:Vous voyez, c'est vraiment une substitution . Le shell substitue une valeur lors de l'expansion qui correspond au chemin vers un lien vers un tuyau . Vous pouvez en profiter - vous n'avez pas besoin d'être contraint d'utiliser ce canal uniquement pour communiquer avec le processus exécuté dans la
()
substitution elle-même ...... qui imprime ...
Maintenant, je sais que différents shells font le coprocessus de différentes manières - et qu'il y a une syntaxe spécifique
bash
pour en configurer un (et probablement un pourzsh
aussi) - mais je ne sais pas comment ces choses fonctionnent. Je sais juste que vous pouvez utiliser la syntaxe ci-dessus pour faire pratiquement la même chose sans tout le rigmarole dans les deuxbash
etzsh
- et vous pouvez faire une chose très similaire dansdash
etbusybox ash
pour atteindre le même but avec ici-documents (parce quedash
etbusybox
faites ici- documents avec des tuyaux plutôt que des fichiers temporaires comme les deux autres) .Donc, lorsqu'il est appliqué à
bc
...... c'est la partie difficile. Et c'est la partie amusante ...
... qui imprime ...
... et il fonctionne toujours ...
... ce qui me donne juste la dernière valeur de
bc
'sa
plutôt que d'appeler laa()
fonction pour l'incrémenter et l'imprimer ...Il continuera de fonctionner, en fait, jusqu'à ce que je le tue et que j'arrache ses tuyaux IPC ...
la source
eval "exec {BCOUT}<>"<(:) "{BCIN}<>"<(:)
fonctionne aussi