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

10

Я использую 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вводилось по запросу программы. Каков наилучший способ сделать это?

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

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

У Вас есть какие-то предложения?

Эндрю
источник
Проверьте этот блог - Запуск интерактивных программ
Suresh

Ответы:

14

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

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

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

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

Kevin
источник
9

Синтаксис, рекомендуемый этим сайтом, называется документом здесь . Ввод в файловую программу начинается сразу под строкой, содержащей ее <<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
Жиль "ТАК - перестань быть злым"
источник
другими словами, EOF в этом контексте означает маркер конца файла , а не фактический конец файла сценария. текст «EOF» - это любой произвольный текст - все, что вы используете сразу после символов <<, будет указывать на конец документа «здесь и сейчас». Я обычно использую EOF, потому что он выделяется и вряд ли будет внутри документа herenow, если, например, я программно генерирую скрипт оболочки (что я делаю довольно часто).
Cas
что полужирный EOF должен быть <подчеркивание> <подчеркивание> EOF <подчеркивание> <подчеркивание>
саз
Используя вот такие документы, я часто менял конечный маркер на что-то гораздо более значимое (и с меньшей вероятностью "случайного" соответствия), например END_OF_WHATEVER_FUNCTION. Иногда попытка «сохранить» пространство / размер на самом деле является пустой тратой усилий, потому что это вызывает неоднозначность относительно того, что на самом деле происходит.
убийца
Как вы можете sleepмежду командами читать из сценария?
boltup_im_coding
@ surprise62 Я не понимаю, о чем ты спрашиваешь. Возможно, вам следует задать новый вопрос на этом сайте. Будьте уверены, чтобы дать достаточно контекста.
Жиль "ТАК - перестань быть злым"
3

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

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

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

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

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

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

саз
источник