Я хочу, чтобы мой скрипт прочитал файл, содержащий пары ключ / значение переменных среды, чтобы установить, а затем установить их.
Пока у меня есть это:
#!/bin/bash
cat $1 | while read kv
do
key=${kv%=*}
val=`echo ${kv#*=} | sed 's/^"\|"$//g'`
export $key="$val"
done
И я хочу прочитать файл так:
XAUTHLOCALHOSTNAME="localhost"
DISPLAY=":0"
XAUTHORITY="/tmp/some-XAuthority"
Мне нужны только эти переменные в области действия в течение всего сценария, поэтому мне не нужно решать проблему установки переменной в сценарии для родительской области действия .
Из моего тестирования я думаю, что моя проблема связана с export $key="$val"
, поэтому я думаю, что мне просто нужна замена для этой линии.
key=${kv%%=*}
лучше, чемkey=${kv%=*}
потому, что %% и ## отличаются от% и # для того, является ли удаленная часть самая короткая или самая длинная съемная частьОтветы:
export $key=$val
должно работать очень хорошо вbash
. Я подозреваю, что ваша проблема - труба (|
). Все команды в конвейере выполняются в подоболочке. В вашем примере, экземпляр того,bash
что выполняется ваш сценарий будет разветвить 2 подоболочки: один дляcat $1
и другой дляwhile read ...
. Переменные назначаются и экспортируются в подоболочке, выполняющей цикл while, а затем все они быстро выбрасываются при выходе из подоболочки. Один из способов исправить это - вообще не создавать подоболочки. Вместо бесполезного использования cat , попробуйте вместо этого перенаправление:BashFAQ 24 объясняет это гораздо более подробно.
Альтернативный подход состоит в том, чтобы просто получить исходный файл с добавлением экспорта:
Это
<( )
процесс замещения.В качестве дополнительного предостережения, поскольку вы читаете переменные среды из аргумента, вы должны убедиться, что файл аргумента
$1
является надежным источником, чтобы он не мог навредить вашему сценарию.источник
cat
. Но скрипт с перенаправлением теперь работает, спасибо!( jw013 уже дал правильный ответ , но я хочу указать еще несколько вопросов.)
Правая часть конвейера работает в собственной оболочке в bash (как и большинство других оболочек, за исключением ATT ksh и zsh). Таким образом, вы устанавливаете переменные среды в подоболочке, которая выполняет цикл, но не в основном процессе оболочки.
Здесь есть простое решение, которое должно заменить бесполезное использование
cat
перенаправления:В общем, если вам нужно предварительно обработать ввод, поместите цикл и оставшуюся часть скрипта (по крайней мере, ту часть, которая нуждается в измененных переменных) внутри блока.
Обратите внимание, что, как правило,
while read line; do …
не совсем перебирать строки ввода. См. Почемуwhile IFS= read
используется так часто, а неIFS=; while read..
? для объяснения. Правильная идиома для перебора входных строкЗдесь удаление начальных и конечных пробелов не имеет значения, так как не должно быть никаких заданных вами входных данных, но вам может потребоваться
-r
избегать расширения с обратной косой чертой. Возможно,while read line
это действительно правильный способ чтения ваших входных данных (но я подозреваю, что только если значения переменных не содержат символов новой строки). Также возможно, что ваш формат ввода является неоднозначным или более сложным для анализа. Проверьте, что произойдет, если значение одной из переменных содержит символ новой строки, двойную кавычку или обратную косую черту.Одна точка, в которой вы определенно искажаете ввод, - это когда вы извлекаете значение:
Во- первых, вы должны использовать двойные кавычки подстановки переменных:
echo "${kv#*=}"
; в противном случае оболочка выполняет разбиение по словам и генерацию имени файла (то есть сглаживание) на нем. Во-вторых,echo
это не надежный способ печати строки, потому что некоторые строки, начинающиеся с a-
, обрабатываются как параметры, а некоторые оболочки выполняют расширение обратной косой черты для аргумента. Надежный и портативный способ печати строкиprintf %s "${kv#*=}"
. Кроме того, если значение занимает несколько строк, программа sed будет работать с каждой отдельно, что неправильно. Это поправимо, но есть более простой способ, который заключается в использовании манипуляции строки средства оболочечного:val=${kv#*=}; val=${val#\"}; val=${val%\"}
.Предполагая, что ваш ввод правильно проанализирован с помощью простого
read
, вот более простой способ его проанализировать, воспользовавшисьIFS
настройкой для разделения каждой строки:источник
Другим хорошим вариантом может быть размещение
export
в файле и его источник:а потом:
источник
/ окр
скрипт
источник