Использование Sed для расширения переменных среды внутри файлов
-
05-07-2019 - |
Вопрос
Я бы хотел использовать Sed для расширения переменных внутри файла.
Предположим, я экспортировал переменную VARIABLE = что-то, и у меня есть " test " файл со следующим:
I'd like to expand this: "${VARIABLE}"
Я пробовал команды, подобные следующим, но безрезультатно:
cat test | sed -e "s/\(\${[A-Z]*}\)/`eval "echo '\1'"`/" > outputfile
Результатом является " выходной файл " с переменной, которая еще не раскрыта:
I'd like to expand this: "something"
Тем не менее, выполнение eval " echo '$ {VARIABLE}'
в консоли bash приводит к значению " что-то " быть эхом Кроме того, я проверил, и этот шаблон полностью соответствует.
Желаемый результат будет
<*>Кто-нибудь может пролить свет на это?
Решение
Рассмотрим пробную версию:
cat test | sed -e "s/\(\${[A-Z]*}\)/`eval "echo '\1'"`/" > outputfile
Причина, по которой это не работает, заключается в том, что это требует предвидения со стороны оболочки. Сценарий sed генерируется до того, как sed сопоставит любой шаблон, поэтому оболочка не сможет выполнить эту работу за вас.
Я делал это несколькими способами в прошлом. Обычно у меня есть список известных переменных и их значений, и я произвел замену из этого списка:
for var in PATH VARIABLE USERNAME
do
echo 's%${'"$var"'}%'$(eval echo "\$var")'%g'
done > sed.script
cat test | sed -f sed.script > outputfile
Если вы хотите отобразить переменные произвольно, то вам нужно либо иметь дело со всей средой (вместо фиксированного списка имен переменных, использовать вывод из env
, соответствующим образом отредактированный), или использовать Вместо этого Perl или Python.
Обратите внимание, что если значение переменной среды содержит косую черту в вашей версии, вы столкнетесь с проблемами, используя косую черту в качестве разделителя полей в нотации s ///. Я использовал «%», поскольку его используют относительно немного переменных окружения, но на некоторых машинах есть такие, которые содержат символы «%», поэтому полное решение сложнее. Вам также нужно беспокоиться о обратной косой черте в значении. Вы, вероятно, должны использовать что-то вроде ' $ (eval echo " \ $$ var " | sed' s / [\%] / \\ & amp; / g ')
', чтобы избежать обратной косой черты и символы процента в значении переменной среды. Окончательное исправление: некоторые версии sed
имеют (или имели) ограниченную емкость для размера сценария - более старые версии HP-UX имели ограничение около 100. Я не уверен, что это все еще вопрос, но это было совсем недавно, 5 лет назад.
Простая адаптация оригинального сценария гласит:
env |
sed 's/=.*//' |
while read var
do
echo 's%${'"$var"'}%'$(eval echo "\$var" | sed 's/[\%]/\\&/g')'%g'
done > sed.script
cat test | sed -f sed.script > outputfile
Однако лучшее решение использует тот факт, что у вас уже есть значения в выводе из env
, поэтому мы можем написать:
env |
sed 's/[\%]/\\&/g;s/\([^=]*\)=\(.*\)/s%${\1}%\2%/' > sed.script
cat test | sed -f sed.script > outputfile
Это в целом безопаснее, потому что оболочка никогда не вычисляет ничего, что не должно оцениваться - вы должны быть очень осторожны с метасимволами оболочки в значениях переменных. Я думаю, что эта версия может столкнуться с какими-либо проблемами, только если какой-то вывод из env
искажен.
Остерегайтесь - написание sed
сценариев с помощью sed
- эзотерическое занятие, но демонстрирующее мощь хороших инструментов.
Все эти примеры не позволяют очистить временные файлы.
Другие советы
Может быть, вы можете обойтись без использования sed:
$ echo $VARIABLE
something
$ cat test
I'd like to expand this: ${VARIABLE}
$ eval "echo \"`cat test`\"" > outputfile
$ cat outputfile
I'd like to expand this: something
Пусть интерполяция переменных оболочки сделает всю работу.