Очевидный способ сделать это имеет много проблем:
# This will fail with certain inputs. HTML will certainly be a problem
# as the '<' and '>' characters will be interpreted as file redirects
$ while read r; do eval echo $r; done < input
Следующий perl должен справиться с проблемой достаточно просто для простых входных данных.
$ perl -pwe 'while(($k,$v) = each %ENV ) { s/\${?$k}?/$v/ }' input
Но это не такничего не делать с такими конструкциями, как $ {FOO-bar}.Если вам нужно обработать такие конструкции, может быть достаточно экранировать все метасимволы оболочки и выполнить цикл while / read:
$ sed -e 's/\([<>&|();]\)/\\\1/g' input | while read -r l; do eval echo "$l"; done
Обратите внимание, что это не является ни надежным, ни безопасным.Посмотрите, что происходит на входе, как:
\; rm -rf /
Я сказал «рассмотреть».Не проверяйте это.Sed вставит обратную косую черту перед точкой с запятой, тогда eval получит строку "\\;"который будет интерпретирован как одиночная обратная косая черта, за которой следует точка с запятой, которая завершает эхо, и будет выполнен rm -rf.Учитывая небезопасную оценку неизвестных входных данных, вероятно, было бы безопаснее придерживаться чего-то вроде perl и явно заменять нужные конструкции sh.Примерно так:
$ perl -pwe 'while(($k,$v) = each %ENV ) { s/\${?$k}?/$v/ };
s/\${[^-]*-([^}]*)}/$1/g' input
У этого проблемы с вводом, например $ {FOO = some-text}.Чтобы надежно получить все конструкции sh ($ {word: rhs}, где ':' может быть любым из '-', '?', '=', '+', '%', '#' Илилюбой из них с предваряющим двоеточием (или множеством других символов, если вы разрешите синтаксис non-posix sh!)) вам придется создать довольно сложный набор сравнений.