
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_ROOT
parâ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 pattern
definido como uma barra literal \/
e string
definido 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'