Использование соответствия префикса имени переменной и косвенного обращения к переменной вbash
:
proj_env_repo_db_username=username
proj_env_repo_db_host=host
proj_env_repo_db_port=port
for variable in "${!proj_env_repo@}"; do
export "TF_ENV${variable#proj_env_repo}"="${!variable}"
done
Цикл использует "${!proj_env_repo@}"
для создания списка имен переменных, которые имеют префикс имени proj_env_repo
. В каждой итерации $variable
будет именем одной из этих переменных.
Внутри цикла export
используется для создания новой переменной среды путем удаления префикса proj_env_repo
и замены его строкой TF_ENV
. Значение для новой переменной окружения получается с помощью косвенной переменной ${!variable}
, т. е. значения переменной, имя которой хранится в $variable
.
Чтобы дополнительно сбросить исходную переменную, используйте unset "$variable"
после export
до конца цикла.
Тестовый запуск с включенной трассировкой:
$ bash -x script.sh
+ proj_env_repo_db_username=username
+ proj_env_repo_db_host=host
+ proj_env_repo_db_port=port
+ for variable in "${!proj_env_repo@}"
+ export TF_ENV_db_host=host
+ TF_ENV_db_host=host
+ for variable in "${!proj_env_repo@}"
+ export TF_ENV_db_port=port
+ TF_ENV_db_port=port
+ for variable in "${!proj_env_repo@}"
+ export TF_ENV_db_username=username
+ TF_ENV_db_username=username
Как функция, принимающая префикс старого имени в качестве первого аргумента и новый префикс в качестве второго аргумента:
rename_var () {
# Make sure arguments are valid as variable name prefixes
if ! [[ $1 =~ ^[a-zA-Z_][a-zA-Z_0-9]*$ ]] ||
! [[ $2 =~ ^[a-zA-Z_][a-zA-Z_0-9]*$ ]]
then
echo 'bad variable name prefix' >&2
return 1
fi
eval 'for variable in "${!'"$1"'@}"; do
export "'"$2"'${variable#'"$1"'}"="${!variable}"
done'
}
Здесь мы прибегаем к использованию eval
поверх цикла, поскольку bash
не поддерживает синтаксис ${!$1@}
. Функция создает соответствующий шелл-код (в виде строки )для переименования переменных в соответствии со значениями $1
и$2
(1-го и 2-го аргументов, переданных функции ), а затем использует eval
для выполнения этого шелл-кода.
Эту функцию можно использовать как
rename_var project_env_repo TF_ENV
... или, используя переменные,
rename_var "$old_variable_prefix" "$new_variable_prefix"
Примечание :При выполнении подобных действий (с использованием eval
пользовательского ввода )вы должны проверить, что код, который вы оцениваете, действителен и соответствует вашим ожиданиям. это быть. В данном случае это означает проверку $1
и $2
как допустимых префиксов имен переменных.В противном случае хотя бы кавычки и }
вызовут синтаксические ошибки в eval
, и есть вероятность внедрения команд.
Примечание :Впервые (я думаю ), что у меня когда-либо было использованиеeval
. Я бы никогда не поставил себя в положение, когда мне нужно использовать приведенный выше код, но я, очевидно, не знаю предыстории вопроса, так что это не настоящая критика вопроса (, который сам по себе интересен. ).
Похожие (на сайте Software Engineering):
Возможно, потому что вы запустили его в 12 :50, где date +%M
дает вам 50, что становится 45, если вычесть 5, и -5, если вычесть 55.
В 12 :00 вы бы тоже получили -5 с первым.
В 12 :07 вы получили бы 12:2
вместо 12:02
, а в 12 :09 некоторые оболочки жаловались, что 09
не является допустимым восьмеричным числом. Вы не можете просто вычесть 5 из поля минут, чтобы получить время на 5 минут раньше.Учтите, что, например, в Jan 1 00:00
это должно дать вам Dec 31 23:55
.
Для расчета даты в Solaris можно использовать perl
или zsh
, хотя последний не всегда установлен по умолчанию. Чтобы получить время, которое было 5 минут назад:
perl -MPOSIX -le 'print strftime("%b %d %R", localtime(time - 5*60))'
или:
zsh -c 'zmodload zsh/datetime; strftime "%b %d %R" $((EPOCHSECONDS - 5*60))'
На самом деле, начиная с версии 11 Solaris, /bin/sh
и /bin/ksh
на самом деле являются ksh93, поэтому вы также можете использовать ksh
там (лучше не sh
, поскольку sh
это в настоящее время реализован ksh93, это может измениться в будущем, а стандартный sh
язык не имеет этих функций):
ksh -c 'printf "%(%b %d %R)T\n" "5 minutes ago"'
Как указано в комментариях @glennjackman, если у вас установлено bash
, вы также можете выполнить:
bash -c 'printf -v t "%(%s)T" -1 && printf "%(%b %d %R)T\n" "$((t - 5*60))"'
(поддержка %s
и достаточно свежая версия bash были добавлены в выпуск 11 Solaris ).
И пока мы собираемся добавить больше языков, если у вас есть интерпретатор TCL, такой какexpect
:
expect -c 'puts [clock format [
clock add [clock seconds] -5 minute] -format "%b %d %R"]'
Илиpython3
:
python3 -c 'import time; print(time.strftime("%b %d %R", time.localtime(time.time() - 5*60)))'