Escape de caracteres de uma variável bash

Escape de caracteres de uma variável bash

Estou tentando pesquisar e substituir strings em um modelo de configuração, usando variáveis ​​bash.

Variáveis ​​Bash

BACKUP_KEY="ABCDEFG"
BACKUP_ROOT="/var/backup"

Modelo de configuração ( template.conf):

GPG_KEY='BACKUP_KEY_ID'
GPG_OPTS="--pinentry-mode loopback"
TARGET='file://BACKUP_ROOT/partA'
SOURCE='/partA'
MAX_AGE=3M

Resultado esperado:

GPG_KEY='ABCDEFG'
GPG_OPTS="--pinentry-mode loopback"
TARGET='file:///var/backup/partA'
SOURCE='/partA'
MAX_AGE=3M

Isso é fácil para o primeiro parâmetro, usando sed, mas a barra invertida no segundo parâmetro precisava ser escapada para 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

Encontrei a extensão bash que permitiria adicionar aspas simples, ou seja ${BACKUP_ROOT@Q}, mas não encontrei até agora uma opção para escapar da barra invertida no BACKUP_ROOTparâmetro.

Eu me pergunto se existe alguma opção elegante para conseguir isso? Observe que eu preciso das variáveis ​​sem escape em vários outros lugares, então eu preferirianãopara defini-los adicionalmente com barras invertidas de escape BACKUP_ROOT_ESC="\\/var\\/backup". Isso definitivamente não seria elegante;)

Eu também preferirianãousar um limitador diferente, porque também tenho outras variáveis, por exemplo, senhas que podem conter outros caracteres que correspondam acidentalmente aos delimitadores de pesquisa/substituição. Portanto, encontrar uma maneira de escapar automaticamente da barra (e talvez também da barra invertida) seria a opção mais confiável.

Responder1

Por uma questão de estilo, você deve evitar todos os nomes de variáveis ​​em letras maiúsculas

Não é um sinalizador de expansão como Q, mas você pode usar o genérico ${parameter//pattern/string}with patterndefinido como uma barra literal \/e stringdefinido como uma barra invertida literal - barra literal \\\/:

$ 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'

informação relacionada