J'ai un programme UNIX de boîte noire utilisé dans un shell Bash qui lit les colonnes de données de stdin, les traite (en appliquant un effet de lissage) puis les sort vers stdout. Je l'utilise par des tuyaux UNIX, comme
generate | smooth | plot
Pour plus de lissage, je peux répéter le lissage, il serait donc appelé depuis la ligne de commande Bash comme
generate | smooth | smooth | plot
ou même
generate | smooth | smooth | smooth | smooth | smooth | smooth | smooth | smooth | smooth | smooth | plot
Cela devient peu sauvage. Je voudrais créer un wrapper Bash pour pouvoir diriger smooth
et réinjecter sa sortie directement dans une nouvelle instance d' smooth
un nombre arbitraire de fois, quelque chose comme
generate | newsmooth 5 | plot
au lieu de
generate | smooth | smooth | smooth | smooth | smooth | plot
Ma première tentative a été un script Bash qui a généré des fichiers temporaires dans le répertoire actuel et les a supprimés, mais qui s'est avéré laid lorsque je ne me trouvais pas dans un répertoire avec accès en écriture, et a également laissé des fichiers inutiles en cas d'interruption.
Il n'y a aucun argument au smooth
programme.
Existe-t-il une manière plus élégante de "boucler" un tel programme pour paramétrer le nombre d'appels?
la source
Réponses:
Vous pouvez l'envelopper dans une fonction récursive:
Vous utiliseriez cela comme
ce qui équivaudrait à
la source
Si vous pouvez vous permettre de taper autant de virgules que le nombre de
smooth
commandes que vous souhaitez, vous pouvez profiter de l'extension d'accolade séparée par des virgules du shell.TL; DR
La ligne de commande entière pour votre exemple de cas serait:
Remarque:
smooth |
|
avantplot
parce que cela est inclus dans la dernièresmooth |
chaîne produite par l'extension Bracesmooth
, tant que vous pouvez les inclure correctement dans la partie fixe citée qui précède l'accolade ouverte; rappelez-vous en tout cas que vous les fournirez à toutes les répétitions de la commandeComment ça fonctionne
L'extension d'accolade séparée par des virgules vous permet de produire dynamiquement des chaînes, chacune composée d'une partie fixe spécifiée et des parties variables spécifiées. Il produit autant de chaînes qu'il y a de parties variables indiquées, comme
a{b,c,d}
produitab ac ad
.La petite astuce ici est que si vous faites plutôt une liste de parties variables vides , c'est-à-dire avec seulement des virgules à l'intérieur des accolades, l'extension d'accolade ne produira que des copies de la partie fixe. Par exemple:
produira:
Notez que 4 virgules produisent 5
smooth
chaînes. Voilà comment fonctionne cette extension d'accolade: elle produit des chaînes autant de virgules plus une.Bien sûr, dans votre cas, vous avez également besoin d'un
|
séparateursmooth
, alors ajoutez-le simplement dans la partie fixe mais veillez à le citer correctement pour que la coque ne l' interprète pas immédiatement. C'est:produira:
Veillez à toujours placer la partie fixe immédiatement à côté de l'entretoise ouverte, c'est-à-dire sans espace entre le
'
et le{
.(Notez également que pour former la partie fixe, vous pouvez également utiliser des guillemets doubles au lieu de guillemets simples, si vous devez développer des variables de shell dans la partie fixe. Prenez juste soin de l'échappement supplémentaire qui est requis lorsque certains caractères spéciaux du shell se produisent dans une chaîne entre guillemets).
À ce stade, vous avez besoin d'un
eval
appliqué à cette chaîne afin que le shell l'interprète enfin comme la commande en pipeline qu'il est censé être.Ainsi, pour résumer le tout, la ligne de commande entière pour votre exemple de cas serait:
la source
eval
lorsque l'on fournit des chaînes non fiables, non filtrées à évaluer, c'est-à-dire lorsqu'elles sont utilisées avec des variables qui peuvent contenir du contenu "inconnu" comme le cas que vous avez lié. D'un autre côté, ileval
peut également être très pratique pour une "plomberie" rapide des commandes, en particulier lorsqu'il est utilisé à l'invite, comme le cas présent semble l'être, oùeval
l'entrée ne serait qu'une chaîne littérale tapée manuellement par l'utilisateur dans personneeval str
par quelque chose de prétentieux et stupide. /dev/stdin <<<str
. Non seulement cela fera une impression sur les imbéciles, mais cela gardera également @CharlesDuffy de votre dos ;-)