Estou tentando fazer um shell script bash que monte, a partir de algumas variáveis pré-obtidas, um arquivo de texto.
Para isso utilizo o sed, alterando os flags do arquivo pelo desejado:
sed "s/this is a line in text/$var/g" file
Funciona corretamente e sem problemas. No entanto, a $var
variável geralmente possui caracteres estranhos, muitas vezes sendo chaves criptográficas, como:
-----BEGIN CERTIFICATE-----
MIID0DCCArigAwIBAgIJAMZxe+Z+DbdtMA0GCSqGSIb3DQEBCwUAME4xCzAJBgNV
BAYTAi0tMQswCQYDVQQIEwItLTELMAkGA1UEBxMCLS0xCzAJBgNVBAoTAi0tMRgw
FgYJKoZIhvcNAQkBFgltZUBteS5vcmcwHhcNMjEwODI1MDgyODMzWhcNMzEwODIz
MDgyODMzWjBOMQswCQYDVQQGEwItLTELMAkGA1UECBMCLS0xCzAJBgNVBAcTAi0t
MQswCQYDVQQKEwItLTEYMBYGCSqGSIb3DQEJARYJbWVAbXkub3JnMIIBIjANBgkq
hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1VtgDdOnhyGGd3OQO+QHcqfiH1wP1wJC
5MPZFm9FOQKC74FscbeLflu+hXVSLQQjP8XgJrbCk+xNe+SFOLMoIG mpxvRsjZU
eLzA5lUR8PvmBvgt1iR s1AQQAyh6R7z5QdwamsjmyoE1Si6maRzeCiv46qmlyet
iUEqbXslMk8N6Pa3KsKskv7BgzSOlfLHuWaZScewViGBSbyKUUYV0ljWbGozs21i
w FftSM6JnyNIq6l0wvGYkpJoDpGyxeNPTykswSO6WsG5o8ogJYOQR3KduUqdalj
tHbBsnGB1PNqfhpkBn75FY 8aNryND+uYkkQu1fGVJG0j2XVcPSPpBywZSwGtcCO
LPTL9OIYlRzzVi vTS CRx4NqSY=
-----END CERTIFICATE-----
Quando isso acontece, o sed
comando é interrompido, resultando em:
sed: -e expression #1, char 39: unterminated `s' command
Entendo que o conteúdo da variável é interpretado por sed
como parte do sed
comando, dando o erro.
Existe uma maneira de enviar a variável para sed
como texto simples e que não seja interpretado? Se não for possível, existe alguma alternativa simples para substituir sed
neste caso?
Atualize com comprovação de que o conteúdo do certificado possui o caractere especial /
.
cat ca.crt | grep "\/"
grep: warning: stray \ before /
5MPZFm9FOQKC74FscbeLflu+hXVSLQQjP8XgJrbCk+xNe+SFOLMoIG/mpxvRsjZU
eLzA5lUR8PvmBvgt1iR/s1AQQAyh6R7z5QdwamsjmyoE1Si6maRzeCiv46qmlyet
gUX/9Bunyu65hQ+h5kV4aWMRgnDH8HoTQsrJQd4eshHwsqgQA3+Oou4m6GLihkfC
QwsENypmlOiOeYvmxBC0X/w/2IeZMEDbmrMO0yUL6No9xQan7wKNFwIDAQABo4Gw
ggEBAJBDpHQBNlFoMjeQrH1szNe+30rp3ECCwXH4L+qKegobZ5/+joWSk84pRF0J
w/FftSM6JnyNIq6l0wvGYkpJoDpGyxeNPTykswSO6WsG5o8ogJYOQR3KduUqdalj
tHbBsnGB1PNqfhpkBn75FY/8aNryND+uYkkQu1fGVJG0j2XVcPSPpBywZSwGtcCO
LPTL9OIYlRzzVi/vTS/CRx4NqSY=
Se assumirmos que "esta é uma linha de texto" consiste em uma palavra, podemos usar um processador de macro:
Onde é "palavra" - Um nome é qualquer sequência de letras, dígitos e sublinhado, em que o primeiro caractere não é um dígito.
Se você inserir o conteúdo de um arquivo (não o valor de uma variável) com
sed
, fica mais fácil:Isso irá analisar o arquivo chamado
file
.^this is a line in text$
Se for encontrada uma linha que coincida com a expressão , o arquivo chamadomycert
é inserido, sem qualquer tipo de interpretação. A linha original defile
é então excluída.Você pode obter isso para ler a partir de sua variável da seguinte forma:
Aqui, em vez de ler a partir de
mycert
quando a linha é encontrada,sed
leremos a partir da entrada padrão, que é fornecida viaprintf
. Isso pressupõe que a linha de gatilho ocorre apenas uma vez emfile
.No caso do certificado, existem apenas dois caracteres problemáticos: uma barra e uma nova linha. Você pode usar a expansão de parâmetros para substituí-los por
\/
e,\n
respectivamente, qual sed entende:Mas, em geral, eu usaria Perl, que sabe quais caracteres vêm de uma variável e quais caracteres fazem parte da sintaxe: