Исходный файл / bin / sh из stdin (из другой программы) не файл

14

Вроде сложно назвать это ...

В основном у меня есть программа, которая при запуске печатает на STDOUT набор переменных оболочки:

$ ./settings
SETTING_ONE="this is setting one"
SETTING_TWO="This is the second setting"
ANOTHER_SETTING="This is another setting".

Я хочу запустить это из сценария оболочки, как если бы STDOUT оценивался с source.

Я хотел бы сделать что-то вроде ...

source `./settings`

... но, конечно, это не работает.

Я знаю, что мог сделать:

./settings >/tmp/file
source /tmp/file

но я действительно не хочу этого делать.

Есть какие-нибудь подсказки?

Majenko
источник

Ответы:

16

Вы можете использовать eval:

eval "$(./settings)"

eval "`./settings`"
Кит
источник
Извините, должен был упомянуть, это / bin / sh, а не bash. $ () не работает. Я обновил вопрос.
Majenko
@Matt: Ну, sh - это удар по большинству систем. Если, конечно, вы имели в виду последние версии Ubuntu, где она была заменена на черту.
Hello71
@Matt: в этом случае, обратные галочки должны работать. Но вы должны добавить и точную версию sh- это может быть символическая ссылка на dash, ash, busybox ... Я не видел копию "настоящего 'sh'" вживую.
user1686
1
@Matt: Итак, у вас там ... интересная система. Тем более что почти все вариации "sh" поддерживают $( )- начиная с оболочки Almquist в 4.3BSD - и это тоже POSIX. (Примечание: не спорю, просто любопытно.)
user1686
$ () существует, он просто не работает в этом случае. FreeBSD 8.2's / bin / sh
Majenko
15

В системах, где /dev/fdдоступно, bash поддерживает подстановку процессов:

source <(./settings)

Здесь <( )расширится до автоматически назначенного пути, по /dev/fd/...которому ./settingsможно прочитать выходные данные .

user1686
источник
1
В руководстве по bash это называется «замена процесса».
Гленн Джекман
6
declare `./settings`

Или конечно ...

export `./settings`

Проверьте это конечно ...

export `echo -e "asdf=test\nqwerty=dvorak"` ; echo $asdf $qwerty

Обработка пробелов:

eval export `./settings`
Hello71
источник
Ага, exportтрюк работает! Спасибо
Majenko
Теперь - как я могу обрабатывать пробелы в значении?
Majenko
@Matt: я не могу использовать обратные пометки в комментариях, поэтому, пожалуйста, смотрите отредактированный ответ.
user1686
@ Grawity: Да, вы можете ...a backtick --> ` <-- and here's another one --> ` <--
Hello71
2

source /dev/stdin < ./settings

Я думаю, что / dev / stdin - это единственная вещь для Linux.

LawrenceC
источник
который пытается найти источник настроек. Даже с «./settings» это не с «./settings»: неоднозначный ('= backtick)
Majenko
/dev/stdinработает на BSD и Cygwin тоже.
user1686
1
Использование |, однако, не будет работать (по крайней мере, не совсем), потому что обе стороны канала являются отдельными подпроцессами, поэтому полученные команды не будут влиять на текущую оболочку.
user1686
1
отредактировано, чтобы отразить это.
LawrenceC
1
Мне нравится этот /dev/stdinтрюк, но то, что делает ваш ответ, на самом деле эквивалентно простому, source ./settingsне выполняя его. Можно было бы использовать документ-здесь , чтобы преодолеть это: source /dev/stdin <<EOF \n $(./settings) \n EOF.
tlwhitec
0

Хотелось представить другую перспективу здесь, так как другие ответы создают файлы и не извлекают напрямую из stdin. У меня есть несколько сборок, которые должны отправить подготовленную информацию о среде в несколько сценариев. То, что я делаю, готовит кучу Bash-совместимых переменных в строке:

Var1="Foo"
Var2="Bar"
Var3="Baz"

Когда я готовлюсь выполнить сценарий, я base64 кодирую приведенную выше многострочную строку и передаю ее в свой сценарий оболочки:

echo base64EncodedParameters | build.sh

В build.sh я читаю из stdin, base64 декодирую и оцениваю результат.

params=""
while read line; do params="${params}${line}"; done
eval `echo $params | base64 -D`

echo "Hello ${Var1} ${Var2}"
Джей Прулкс
источник