Tengo un programa UNIX de recuadro negro utilizado en un shell Bash que lee columnas de datos de stdin, los procesa (aplicando un efecto de suavizado) y luego los envía a stdout. Lo uso por tuberías UNIX, como
generate | smooth | plot
Para más suavizado, puedo repetir el suavizado, por lo que se invocará desde la línea de comando Bash como
generate | smooth | smooth | plot
o incluso
generate | smooth | smooth | smooth | smooth | smooth | smooth | smooth | smooth | smooth | smooth | plot
Esto se está volviendo extraño. Me gustaría hacer un contenedor Bash para poder canalizar smooth
y alimentar su salida de nuevo a una nueva instancia de smooth
un número arbitrario de veces, algo así como
generate | newsmooth 5 | plot
en lugar de
generate | smooth | smooth | smooth | smooth | smooth | plot
Mi primer intento fue un script Bash que generó archivos temporales en el directorio actual y los eliminó, pero eso se volvió feo cuando no estaba en un directorio con acceso de escritura, y también dejaba archivos basura cuando se interrumpía.
No hay argumentos para el smooth
programa.
¿Hay una manera más elegante de "envolver" un programa para parametrizar el número de llamadas?
fuente
Respuestas:
Podría envolverlo en una función recursiva:
Usarías esto como
que sería equivalente a
fuente
Si puede permitirse escribir tantas comas como la cantidad de
smooth
comandos que desee, puede aprovechar la Expansión de llaves separada por comas del shell.TL; DR
La línea de comandos completa para su caso de muestra sería:
Nota:
smooth |
|
antesplot
porque está incluido en la últimasmooth |
cadena producida por la expansión Bracesmooth
, siempre y cuando pueda incluirlos correctamente dentro de la parte fija citada que precede a la llave abierta; en cualquier caso, recuerde que los proporcionará a todas las repeticiones del comandoCómo funciona
La expansión de llaves separadas por comas le permite producir cadenas dinámicamente, cada una hecha de una parte fija específica más las partes variables especificadas. Produce tantas cadenas como hay partes variables indicadas, como
a{b,c,d}
produceab ac ad
.El pequeño truco aquí es que si prefiere hacer una lista de partes variables vacías , es decir, con solo comas dentro de las llaves, la expansión de llaves solo producirá copias de la parte fija solamente. Por ejemplo:
Producirá:
Tenga en cuenta que 4 comas produce 5
smooth
cadenas. Así es como funciona esta expansión Brace: produce cadenas de comas más una.Por supuesto, en su caso, también necesita
|
separar cada unosmooth
, así que solo agréguelo en la parte fija pero tenga cuidado de citarlo correctamente para que el shell no lo interprete de inmediato. Es decir:Producirá:
Tenga cuidado de colocar siempre la parte fija inmediatamente adyacente a la llave abierta, es decir, sin espacios entre el
'
y el{
.(Tenga en cuenta también que para formar la parte fija también puede usar comillas dobles en lugar de comillas simples, si necesita expandir las variables de shell en la parte fija. Solo tenga cuidado con el escape adicional que se requiere cuando aparecen caracteres especiales de shell dentro de una cadena con comillas dobles).
En este punto, necesita una
eval
aplicación a esa cadena para que el shell finalmente la interprete como el comando canalizado que se supone que es.Por lo tanto, para resumirlo todo, la línea de comandos completa para su caso de muestra sería:
fuente
eval
cuando uno proporciona cadenas no confiables y no desinfectadas para que evalúe, es decir, cuando se usa con variables que pueden llevar contenido "desconocido" como el caso que vinculó. Por otro lado,eval
también puede ser muy útil para la "plomería" rápida de comandos, especialmente cuando se usa en el indicador, como parece ser el caso en cuestión, dondeeval
la entrada solo sería una cadena literal escrita manualmente por el usuario en personaeval str
por algo pretencioso y estúpido. /dev/stdin <<<str
. Esto no solo causará impresión en los tontos, sino que también mantendrá a @CharlesDuffy lejos de tu espalda ;-)