我正在尝试制作一个 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}/'