Экранирование символов из переменной bash

Экранирование символов из переменной bash

Я пытаюсь выполнить поиск и замену строк в шаблоне конфигурации, используя переменные 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'

Связанный контент