当变量是随机(证书)文本时,如何将 sed 与变量一起使用

当变量是随机(证书)文本时,如何将 sed 与变量一起使用

我正在尝试制作一个 bash shell 脚本,该脚本从一些预先获得的变量中安装一个文本文件。

为此,我使用 sed,按所需更改文件的标志:

sed "s/this is a line in text/$var/g" file

它工作正常且没有问题。然而,该$var变量通常具有奇怪的字符,通常是加密密钥,例如:

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

发生这种情况时,sed命令会中断,导致:

sed: -e expression #1, char 39: unterminated `s' command

我知道变量的内容被解释为命令sed的一部分sed,从而给出错误。

有没有办法将变量sed以纯文本形式发送并且不被解释?如果不可能,sed在这种情况下是否有任何简单的替代方法可以替换?


更新证明,证明证书内容具有特殊字符/

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=

答案1

如果使用 插入文件的内容(而不是变量的值)sed,则更容易:

sed -e '/^this is a line in text$/r mycert' -e '//d' file

这将解析名为file.如果^this is a line in text$找到与表达式匹配的行,mycert则插入所调用的文件,而不进行任何类型的解释。file然后删除原来的行。

您可以像这样从变量中读取它:

printf '%s\n' "$var" |
sed -e '/^this is a line in text$/r /dev/stdin' -e '//d' file

在这里,不是从mycert找到该行时读取,而是sed从通过 提供的标准输入读取printf。这假设触发线仅在 中出现一次file

答案2

如果我们假设“这是文本中的一行”由一个单词组成,那么我们可以使用宏处理器:

m4 -Dword="$var" file

其中“单词” - 名称是字母、数字和下划线的任意序列,其中第一个字符不是数字。

答案3

对于证书来说,只有两个有问题的字符:斜杠和换行符。您可以使用参数扩展将它们分别替换为sed 可以理解的\/和:\n

var=${var//$'\n'/\\n/}
var=${var//\//\\\/}
sed "s/text/$var/"

但一般来说,我会使用 Perl,它知道哪些字符来自变量以及哪些字符是语法的一部分:

var=$var perl -pe 's/text/$ENV{var}/'

相关内容