Автоматизация текстового ввода из скрипта bash без использования EOF

Автоматизация текстового ввода из скрипта bash без использования EOF

Я использую Ubuntu Linux. Предположим, что есть программа под названием myprogram. Эта программа запрашивает у пользователя ввод данных; в частности, пользователь должен ввести целое число при появлении запроса и нажать Enter. Я хотел бы автоматизировать этот процесс с помощью скрипта bash. В частности, я хотел бы выполнить myprogram, скажем, 100 раз (используя счетчик i, который идет от 1до 100). При каждом выполнении myprogramя хотел бы вводить текущее значение iпри появлении запроса.

(Кстати, myprogramпринимает параметры/переключатели -options, все из которых будут постоянными и, таким образом, будут указаны в скрипте bash.)

Неполный скелет этого bash-скрипта может быть таким:

#!/bin/bash
for i in {1..100}
do
   myprogram -options
done

Теперь я хотел бы изменить код выше так, чтобы текущее значение iвводилось по запросу программы. Как лучше всего это сделать?

Сайт программного обеспечения, которое я использую, предлагаетusing <<EOFв конце строки myprogram -options. Я думаю, что это говорит bash искать "конец файла" для ввода, который нужно использовать. Но что, если я не хочу размещать ввод вконецфайла? Что делать, если я хочу поместить его сразу после <<или <?

Причина в том, что все станет сложнее. Например, я могу ввести целочисленный счетчик, jкоторый изменяется каким-то нелинейным, непоследовательным образом. Затем я хотел бы передавать текущее значение в jна myprogramкаждой итерации, но значение jможет измениться между вызовом в myprogram -optionsи концом файла EOF.

Есть ли у вас какие-либо предложения?

решение1

Почти для всех программ оба варианта echo $i | myprogram -optionsдолжны myprogram -options <<<$iработать, если передавать программу $iчерез стандартный ввод.

<fooбудет использовать содержимое файла с именем foostdin.

<<fooбудет использовать текст между этим и строкой, состоящей исключительно из fooкак стандартный ввод. Этоздесь документ(heredoc), как сказал Жиль; EOFна самом деле не означает конец файла, это просто обычный разделитель heredoc (в этом примере мы используем «foo»).

<<<fooбудет использовать строку "foo" как стандартный ввод. Вы также можете указать переменную $foo, и оболочка будет использовать ее содержимое как stdin, как я показал выше. Это называетсяздесьстрока, так как он использует короткую строку в отличие от целого блока, как в heredoc. Herestrings работают в bash, но не в /bin/sh.

решение2

Синтаксис, рекомендуемый этим сайтом, называетсяздесь документ. Ввод в файл program начинается сразу под строкой, содержащей <<EOF, и он не завершается концом скрипта, а строкой, содержащей именно текст EOF(следите за тем, чтобы не было лишних пробелов). Кстати, вы можете использовать любой маркер конца, который не содержит никаких специальных символов оболочки: EOFэто не ключевое слово, это просто традиция.

#!/bin/bash
for i in {1..100}
do
   myprogram -options <<EOF
$i
EOF
   for j in {1..42}; do
     myprogram2 <<EOF
$i
$j
EOF
   done
done

решение3

здесь документы, упомянутые Кевином и Жилем выше, или простая трубная обвязка будут работать во многих случаях.

Для более сложных ситуаций вы можете рассмотреть Expect или что-то подобное (например, модуль Expect::Simple CPAN — очень простая в использовании реализация perl). Лично я предпочитаю модуль perl (сам Expect — это tcl), но существуют реализации для многих распространенных языков сценариев. Можно даже написатьоченьпримитивная реализация идеи на sh или bash с использованием while и read.

Основная идея Expect и подобных инструментов заключается в ожидании указанной строки или шаблона в выходных данных программы, а затем в передаче ей любых необходимых входных данных.

Распространенным примером использования является автоматизация входа в систему путем «ожидания» (т. е. ожидания) строки «ogin:», отправки имени для входа, затем ожидания строки «word:» и отправки пароля.

Последний вариант, если у вас есть исходный код myprogram, — просто изменить его так, чтобы он принимал ввод, который вы хотите ему передать, как параметр командной строки. Это может потребовать немного больше работы на начальном этапе, но будет намного менее раздражающим, чем возня с Expect или передача данных в программу, которая не была разработана для использования таким образом.

... и не забудьте отправить свой патч в myprogram обратно в апстрим :) Даже если им не нравится, как вы его закодировали, им может понравиться идея настолько, что они сами добавят эту функцию. Разработчики апстрима, как правило, ценят людей, которые поднимают свои задницы и вносят свой вклад, а не требуют или жалуются.

Связанный контент