Передайте текст програмі, що очікує файл


30

Пов’язане із запитанням, яке я задав щодо переповнення стека: передача декількох рядків коду до wsadmin.sh? .

Як рядок, у мене є кілька рядків введення, які мені потрібно подати в команду. Однак команда приймає лише файл, повний вводу.

Чи є якимось чином я міг би зберігати рядки у тимчасовому файлі чи трубі, які ніколи насправді не записуються на диск, а потім подавати їх безпосередньо в програму?

Як я можу здобути трубу, подати вхід у неї, передати цю команду команді, а потім позбутися її?


2
Чи можете ви додати приклад команди, яку ви використовуєте, і як її слід викликати?
Прорив

2
Це означає, що програма не приймає stdin?
Лео Лам

Я згоден з обома коментаторами вище. Неможливо запропонувати нічого, що може спрацювати, не знаючи специфікацій програми.
Ларссенд

Відповіді:


27

Іншим рішенням є використання Process Substitution в Bash. Якщо ваша система назвала труби, ви можете скористатися цією функцією.

Він використовується так:

program_expecting_a_file <(list)

де listпослідовність команд оболонки (фактично трубопроводи, повні деталі тут ). listбуде виконано, а його вихід буде підключений до труби. Потім назва труби передається вашій програмі.

ПРИМІТКА: проміжки між <та та не допускаються (.

(Інша заміна >(list)також працює так, як ви очікували.)

У вашому конкретному випадку ви можете використовувати

program_expecting_a_file <(echo "$your_strings")

хоча ви можете вважати рішення @ meuh більш елегантним.

Оновлення. Дуже багато прикладів використання можна знайти в Посібнику з розширеного сценарію Bash .


Інші два не спрацювали навіть у самих тривіальних випадках. Ваш проходить тести, які я до цього часу кинув. Я поки що схвалив вашу. Я повернусь і відзначу це як прийняте, якщо воно зробить все, що мені потрібно.
ArtOfWarfare

Ваш працює чудово. Якщо ви хочете, ви можете додати його до відповідного питання на StackOverflow, і я можу прийняти його і там. stackoverflow.com/questions/31374202 / ...
ArtOfWarfare

Привіт @ArtOfWarfare, радий допомогти. Там уже є коментар із тим же запропонованим рішенням, тому мені було б неправильно розміщувати відповідь там.
Едвард

Ви розмістили своє рішення до того, як він зробив. У будь-якому разі я попросив його змінити свій коментар на відповідь, щоб я міг його прийняти. Якщо жоден із вас не опублікує відповіді протягом ~ 24 годин на це запитання, я просто опублікую відповідь, щоб я міг прийняти її (мені не подобається залишати мої запитання як такі, що не відповідають, як тільки я знайшов відповідь. просто погані манери для майбутніх читачів / потенційних відповідей на запитання.)
ArtOfWarfare

Привіт @ArtOfWarfare, я абсолютно добре з тим, що ти пропонуєш!
Едвард

15

Ви можете використовувати bash тут, док . Наприклад,

$ cat -n <<<'a
> b'
 1  a
 2  b

Якщо ви маєте щось у змінній bash, ви також можете інтерполювати це: напр <<<"path is $PATH".


Якщо ваша команда наполягає на імені файлу, ви можете надати її /dev/stdin. Наприклад:

$ sed -f /dev/stdin <<<'s/a/b/'

виробляє висновок: s/b/b/.


З питання, чи команда приймає вхід stdin, не зрозуміло , і якщо ні, це не спрацює. Я сподіваюся, що ОП уточнить.
David Z

1
:( - Це здалося надто перспективним, але коли я спробував це, я отримав повідомлення про помилку"-f" option must be followed by a file name.
ArtOfWarfare

Тут док - це для stdin. Якщо вашій команді абсолютно потрібне -fі ім'я файлу, тоді вкажіть ім'я файлу /dev/stdin. Дивіться мою редакцію.
meuh

Я думаю, що після редагувань це абсолютно життєздатний варіант!
Едвард

1
+1 для /dev/stdinпропозиції. Програма, яку я намагаюся викликати, приймає лише ім'я файлу, тому я поєднав /dev/stdinгередок.
Х'ю Уолтерс

7

Залежно від того, що є в скрипті, ви можете використовувати спеціальне ім'я файлу - (мінус), яке означає stdin

$ mycmd -
Line 1
Line 2
^D

Ще один метод, який може працювати для вас, - це відкрити файл, /dev/fd/0який знову означає stdin .

Третім варіантом може бути створення FIFO (First In First Out). Це як файл, але у нього два кінці - ви пишете в один кінець і читаєте з іншого.

-- Process 1 --                  -- Process 2 --
$ mkfifo foo
$ cat foo
<waits>                          $ echo hello > foo
hello                            $
$ rm foo

3
Можливо, варто відзначити, що програма повинна бути написана для тлумачення -цього способу - це не особливість оболонки чи операційної системи. Хоча, звичайно, більшість стандартних утиліт Linux дотримуються цієї конвенції, наскільки я знаю.
David Z

1
Ні. Це не працює для програми. Є інтерактивний режим, але я хочу передати команди для виконання цієї програми з іншої програми, і я не хочу потрапляти в кролячу яму, яка є expect.
ArtOfWarfare

@ArtOfWarfare Я щойно додав третій варіант, який може працювати.
Majenko

Гарна відповідь! Другий та третій варіанти в основному схожі на <()рішення, але більш чіткі - що може бути дуже корисним!
Едвард

4

Є ще один варіант, подібний до mycmd -рішення, але навіть для програм, які не обробляють -конкретно:

$ mycmd /dev/stdin
Line 1
Line 2
^D

/dev/stdin начебто пов’язана з ОС, і вона працює для мене на Debian GNU / Linux, але я не впевнений, де ще це працюватиме.


1
Здається, це може спрацювати, але що це ^D?
ArtOfWarfare

^Dє загальним позначенням для натискання клавіші Ctrl-D. ^ D тут має семантику "кінця вхідного потоку". Це, мабуть, частіше зустрічається у ^Cабо в ^Zякому стенді для натискання Ctrl-C відповідно для натискання Ctrl-Z.
Аксель Беккерт

1
Це, здається, працює, але як би я програмно вклав речі /dev/stdinі потім закрив їх?
ArtOfWarfare

1
Просто вкладіть щось у цю команду, і воно повинно працювати, тобто cat content | mycmd /dev/stdin. Просто уявіть інші команди, ніж catтут.
Аксель Беккерт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.