Рассмотрим вашу пробную версию:
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/[\%]/\\&/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
- эзотерическое занятие, но иллюстрирующее силу хороших инструментов.
Все эти примеры не позволяют очистить временные файлы.