Использование Sed для расширения переменных среды внутри файлов

StackOverflow https://stackoverflow.com/questions/1609423

  •  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

Пусть интерполяция переменных оболочки сделает всю работу.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top