有两条简单而安全的规则不仅适用于sh
但是也bash
.
1.将整个字符串放在单引号中
这适用于除单引号本身之外的所有字符。要转义单引号,请关闭前面的引号,插入单引号,然后重新打开引号。
'I'\''m a s@fe $tring which ends in newline
'
sed命令:sed -e "s/'/'\\\\''/g; 1s/^/'/; \$s/\$/'/"
2. 用反斜杠转义每个字符
这适用于除换行符之外的所有字符。对于换行符,请使用单引号或双引号。仍必须处理空字符串 - 替换为""
\I\'\m\ \a\ \s\@\f\e\ \$\t\r\i\n\g\ \w\h\i\c\h\ \e\n\d\s\ \i\n\ \n\e\w\l\i\n\e"
"
sed命令:sed -e 's/./\\&/g; 1{$s/^$/""/}; 1!s/^/"/; $!s/$/"/'
.
2b. 2 的更具可读性的版本
有一组简单安全的字符,例如[a-zA-Z0-9,._+:@%/-]
,可以不转义以使其更具可读性
I\'m\ a\ s@fe\ \$tring\ which\ ends\ in\ newline"
"
sed命令:LC_ALL=C sed -e 's/[^a-zA-Z0-9,._+@%/-]/\\&/g; 1{$s/^$/""/}; 1!s/^/"/; $!s/$/"/'
.
请注意,在 sed 程序中,我们无法知道输入的最后一行是否以换行字节结束(除非它为空)。这就是为什么上面的两个 sed 命令都假设它不存在。您可以手动添加带引号的换行符。
请注意,shell 变量仅针对 POSIX 意义上的文本定义。未定义处理二进制数据。对于重要的实现,二进制可以使用除 NUL 字节之外的例外(因为变量是使用 C 字符串实现的,并且旨在用作 C 字符串,即程序参数),但您应该切换到“二进制”语言环境,例如 latin1 。
(您可以通过阅读 POSIX 规范轻松验证规则sh
。对于 bash,请检查参考手册 http://www.gnu.org/software/bash/manual/bashref.html#Quoting由@AustinPhillips 链接)