
Я пытаюсь выполнить поиск и замену строк в шаблоне конфигурации, используя переменные bash.
Переменные Bash
BACKUP_KEY="ABCDEFG"
BACKUP_ROOT="/var/backup"
Шаблон конфигурации ( template.conf
):
GPG_KEY='BACKUP_KEY_ID'
GPG_OPTS="--pinentry-mode loopback"
TARGET='file://BACKUP_ROOT/partA'
SOURCE='/partA'
MAX_AGE=3M
Ожидаемый результат:
GPG_KEY='ABCDEFG'
GPG_OPTS="--pinentry-mode loopback"
TARGET='file:///var/backup/partA'
SOURCE='/partA'
MAX_AGE=3M
Это легко сделать для первого параметра, используя sed
, но обратную косую черту во втором параметре необходимо экранировать для sed
.
# What I try
sed "s/BACKUP_KEY/${BACKUP_KEY}/g; s/BACKUP_ROOT/${BACKUP_ROOT}/g" template.conf > ~/.duply/partA/conf
# What this becomes
sed "s/BACKUP_KEY/ABCDEFG/g; s/BACKUP_ROOT//var/backup/g" template.conf > ~/.duply/partA/conf
Я нашел расширение bash, которое позволяет добавлять одинарные кавычки, т. е. ${BACKUP_ROOT@Q}
, но пока не нашел возможности экранировать обратную косую черту в BACKUP_ROOT
параметре.
Интересно, есть ли какой-нибудь элегантный способ добиться этого? Обратите внимание, что мне нужны неэкранированные переменные в нескольких других местах, поэтому я бы предпочелнетдополнительно определить их с помощью экранирующих обратных косых черт BACKUP_ROOT_ESC="\\/var\\/backup"
. Это было бы определенно не элегантно ;)
Я бы также предпочелнетиспользовать другой ограничитель, потому что у меня есть и другие переменные, например, пароли, которые могут содержать другие символы, случайно совпадающие с разделителями поиска/замены. Поэтому, найти способ автоматически экранировать слеш (а может быть, и обратный слеш) было бы самым надежным вариантом.
решение1
Из соображений стиля следует избегать написания имен переменных заглавными буквами.
Это не флаг расширения, как Q
, но вы можете использовать общий флаг ${parameter//pattern/string}
с pattern
установленным на буквальный слэш \/
и string
установленным на буквальный обратный слэш - буквальный слэш \\\/
:
$ echo "${BACKUP_ROOT}"
/var/backup
$ echo "${BACKUP_ROOT//\//\\\/}"
\/var\/backup
$ echo "TARGET='file://BACKUP_ROOT/partA'" | sed "s/BACKUP_ROOT/${BACKUP_ROOT//\//\\\/}/"
TARGET='file:///var/backup/partA'