Estoy ejecutando Ubuntu Linux. Supongamos que hay un programa llamado myprogram
. Este programa solicita al usuario que ingrese; específicamente, el usuario debe escribir un número entero cuando se le solicite y presionar Enter. Me gustaría automatizar este proceso usando un script bash. En particular, me gustaría ejecutar myprogram
, digamos, 100 veces (usando un contador i
que va de 1
a 100
). En cada ejecución de myprogram
, me gustaría ingresar el valor actual de i
cuando se me solicite.
(Por cierto, myprogram
toma opciones / modificadores -options
, todos los cuales serán constantes y, por lo tanto, se especificarán dentro del script bash).
Un esqueleto incompleto de este script bash podría ser:
#!/bin/bash
for i in {1..100}
do
myprogram -options
done
Ahora me gustaría modificar el código anterior para que i
se ingrese el valor actual de cuando el programa lo solicite. ¿Cuál es la mejor manera de hacer esto?
El sitio web del software que estoy usando sugiere usarlo <<EOF
al final de la myprogram -options
línea. Creo que esto le dice a bash que mire el "final del archivo" para la entrada a usar. Pero, ¿qué pasa si no quiero colocar la entrada al final del archivo? ¿Qué pasa si me gustaría ponerlo inmediatamente después de <<
o <
?
La razón es que las cosas se pondrán más complicadas. Por ejemplo, puedo introducir un contador entero j
que cambia de una manera no lineal, no secuencial. Entonces me gustaría alimentar el valor actual de j
a myprogram
en cada iteración, pero el valor de j
puede cambiar entre la llamada myprogram -options
y el final del archivo EOF
.
¿Tienes alguna sugerencia?
Respuestas:
Para casi todos los programas, tanto
echo $i | myprogram -options
ymyprogram -options <<<$i
debería funcionar, alimentando el programa$i
a través de la entrada estándar.<foo
utilizará el contenido del archivo denominadofoo
stdin.<<foo
utilizará el texto entre eso y una línea que consiste únicamentefoo
como entrada estándar. Este es un documento aquí (heredoc), como dijo Gilles;EOF
en realidad no significa el final del archivo, es solo un delineador heredoc común (en este ejemplo usamos "foo").<<<foo
utilizará la cadena "foo" como entrada estándar. También puede especificar una variable$foo
, y el shell usará su contenido como stdin, como lo mostré anteriormente. Esto se llama herejía , ya que usa una cadena corta en contraste con un bloque completo, como en un heredoc. Las herejías funcionan en bash, pero no en/bin/sh
.fuente
La sintaxis recomendada por este sitio web se denomina documento aquí . La entrada al programa de archivo comienza inmediatamente debajo de la línea que contiene
<<EOF
, y no termina al final del script, sino por una línea que contiene exactamente el textoEOF
(tenga cuidado de no tener espacios en blanco adicionales). Por cierto, puede usar cualquier marcador final que no contenga ningún carácter especial de shell:EOF
no es una palabra clave, es simplemente tradicional.fuente
END_OF_WHATEVER_FUNCTION
. A veces, tratar de "ahorrar" espacio / tamaño es en realidad una pérdida de esfuerzo porque causa ambigüedad sobre lo que realmente está sucediendo.sleep
leer entre los comandos del script?aquí los documentos mencionados por Kevin y Gilles anteriormente, o la tubería simple funcionará en muchos casos.
Para situaciones más complicadas, es posible que desee examinar Expect o similar (por ejemplo, el módulo Expect :: Simple CPAN es una implementación perl muy fácil de usar). personalmente, prefiero el módulo perl (se espera que sea tcl) pero hay implementaciones para muchos lenguajes de script comunes. Incluso es posible escribir una implementación muy primitiva de la idea en sh o bash usando while y read.
La idea general de Expect y herramientas similares es esperar una cadena o patrón específico en la salida de un programa y luego alimentarlo con la entrada que desee.
Un ejemplo de uso común es automatizar el inicio de sesión, "esperando" (es decir, esperando) la cadena "ogin:", envíe el nombre de inicio de sesión, luego espere la cadena "palabra:" y envíe la contraseña.
Una opción final, si tiene la fuente de myprogram, es simplemente modificarla para tomar la entrada que desea dar como una opción de línea de comando. Esto podría ser un poco más de trabajo por adelantado, pero será mucho menos irritante que jugar con Expect o canalizar datos en un programa que no fue diseñado para usarse de esa manera.
... y no olvides enviar tu parche a myprogram nuevamente :) Incluso si no les gusta la forma en que lo has codificado, tal vez les guste la idea lo suficiente como para agregar la función ellos mismos. Los desarrolladores ascendentes tienden a apreciar a las personas que se salen de su trasero y contribuyen en lugar de exigir o quejarse.
fuente