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


10

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

(До речі, myprogramприймає параметри / перемикачі -options, всі вони будуть постійними і таким чином задаються в рамках bash-скрипту.)

Неповним скелетом цього баш-сценарію може бути:

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

Тепер я хотів би змінити вищевказаний код так, щоб поточне значення iвводилося при запрошенні програми. Який найкращий спосіб зробити це?

Веб-сайт програмного забезпечення, яке я використовую, пропонує використовувати <<EOFв кінці myprogram -optionsрядка. Я думаю, що це підказує bash дивитись на "кінець файлу" для введення для використання. Але що робити, якщо я не хочу розміщувати дані в кінці файлу? Що робити, якщо я хотів би поставити його відразу після <<або <?

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

Чи є у вас якісь пропозиції?


Відповіді:


14

Майже всі програми, як echo $i | myprogram -optionsі myprogram -options <<<$iповинні працювати, подають програму за $iдопомогою стандартного введення.

<fooбуде використовувати вміст файлу, названого foostdin.

<<fooбуде використовувати текст між цим і рядком, що складається виключно зі fooстандартного введення. Це тут документ (гередок), як сказав Гілл; EOFнасправді не означає кінець файлу, це просто загальний роздільник гередока (в цьому прикладі ми використовуємо "foo").

<<<fooбуде використовувати рядок "foo" як стандартний вхід. Ви також можете вказати змінну $foo, і оболонка буде використовувати її вміст як stdin, як я показав вище. Це називається герестингом , оскільки в ньому використовується коротка струна на відміну від цілого блоку, як у гередоку. Herestrings працює в bash, але не в /bin/sh.


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, оскільки він виділяється і навряд чи буде знаходитись у документі, що зараз, якщо, наприклад, я програмую сценарій оболонки (що я роблю досить часто).
cas

що сміливий EOF повинен бути <underscore><underscore>EOF<underscore> <underscore>
cas

Використовуючи такі документи, як цей, я часто міняв кінцевий маркер на щось набагато більш значуще (і менш імовірно, що воно буде "випадковим чином"), наприклад END_OF_WHATEVER_FUNCTION. Іноді намагання "заощадити" простір / розмір насправді є марною витратою зусиль, оскільки це викликає неоднозначність щодо того, що насправді відбувається.
вбивця

Як можна sleepміж командами читати зі сценарію?
boltup_im_coding

@ несподівано62 Я не розумію, про що ви питаєте. Напевно, ви повинні задати нове запитання на цьому сайті. Обов’язково дайте достатній контекст.
Жил "ТАК - перестань бути злим"

3

тут документи, про які згадували і Кевін, і Жил, вище, або прості трубопроводи працюватимуть у багатьох випадках.

Для більш складних ситуацій ви можете заглянути в очікувані або подібні (наприклад, модуль Expect :: Simple CPAN - це дуже проста у використанні реалізація perl). особисто я віддаю перевагу модулю perl (очікується, що це tcl), але є реалізація для багатьох поширених мов сценаріїв. Можна навіть написати дуже примітивну реалізацію ідеї в ш або bash, використовуючи час і читання.

Загальна ідея Expect та подібних інструментів полягає в тому, щоб дочекатися заданого рядка або шаблону у висновку програми, а потім подати на нього будь-який вхід.

Поширений приклад використання - це автоматизація входу, "очікуючи" (тобто чекаючи) рядка "ogin:", надіслати ім'я для входу, а потім очікувати рядок "слово:" та надіслати пароль.

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

... і не забудьте надіслати свій патч в мою програму назад за течією :) Навіть якщо їм не подобається спосіб, який ви закодували, їм може сподобатися ідея, достатня для того, щоб додати функцію самостійно. Більш високі динаміки, як правило, цінують людей, які виходять з недопалок і роблять внесок, а не вимагають чи скаржаться.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.