在Bash中是否有需要转义的字符的综合列表?仅仅用sed可以检查吗?
特别是,我正在检查%是否需要转义。我试着
echo "h%h" | sed 's/%/i/g'
并工作良好,没有逃脱%。这是否意味着%不需要转义?这是检查必要性的好方法吗?
更一般的是:它们是shell和bash中转义的相同字符吗?
在Bash中是否有需要转义的字符的综合列表?仅仅用sed可以检查吗?
特别是,我正在检查%是否需要转义。我试着
echo "h%h" | sed 's/%/i/g'
并工作良好,没有逃脱%。这是否意味着%不需要转义?这是检查必要性的好方法吗?
更一般的是:它们是shell和bash中转义的相同字符吗?
当前回答
为了不让别人不得不RTFM…在bash中:
用双引号括起来的字符会保留引号内所有字符的文字值,除了$、'、\和(当启用历史扩展时)!
...所以如果你转义了这些(当然还有引用本身),你可能就没事了。
如果你采取更保守的“当有疑问时,转义它”的方法,应该可以通过不转义标识符字符(即ASCII字母、数字或“_”)来避免获得具有特殊含义的字符。这是非常不可能的(即在一些奇怪的posix shell中)有特殊的含义,因此需要转义。
其他回答
有两个简单而安全的规则,它们不仅可以在sh中工作,还可以在bash中工作。
1. 把整个字符串放在单引号中
这适用于所有字符,除了单引号本身。若要转义单引号,请关闭它前面的引号,插入单引号,然后重新打开引号。
'I'\''m a s@fe $tring which ends in newline
'
Sed命令:Sed -e "s/'/'\\\\ " /g;1年代/ ^ / /;\ s / \ /美元/”
2. 用反斜杠转义每个char
这适用于除换行符以外的所有字符。换行符使用单引号或双引号。空字符串仍然必须处理-替换为""
\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 / /美元“/”。
2 b。更可读的版本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命令都假设它不存在。您可以手动添加带引号的换行符。
注意,外壳变量仅为POSIX意义上的文本定义。没有定义如何处理二进制数据。对于重要的实现,二进制除了NUL字节(因为变量是用C字符串实现的,意味着被用作C字符串,即程序参数),但您应该切换到“二进制”语言环境,例如latin1。
(你可以通过阅读sh的POSIX规范来验证规则。对于bash,查看@AustinPhillips链接的参考手册)
使用打印'%q'技术,我们可以运行一个循环来找出哪些字符是特殊的:
#!/bin/bash
special=$'`!@#$%^&*()-_+={}|[]\\;\':",.<>?/ '
for ((i=0; i < ${#special}; i++)); do
char="${special:i:1}"
printf -v q_char '%q' "$char"
if [[ "$char" != "$q_char" ]]; then
printf 'Yes - character %s needs to be escaped\n' "$char"
else
printf 'No - character %s does not need to be escaped\n' "$char"
fi
done | sort
它给出如下输出:
No, character % does not need to be escaped
No, character + does not need to be escaped
No, character - does not need to be escaped
No, character . does not need to be escaped
No, character / does not need to be escaped
No, character : does not need to be escaped
No, character = does not need to be escaped
No, character @ does not need to be escaped
No, character _ does not need to be escaped
Yes, character needs to be escaped
Yes, character ! needs to be escaped
Yes, character " needs to be escaped
Yes, character # needs to be escaped
Yes, character $ needs to be escaped
Yes, character & needs to be escaped
Yes, character ' needs to be escaped
Yes, character ( needs to be escaped
Yes, character ) needs to be escaped
Yes, character * needs to be escaped
Yes, character , needs to be escaped
Yes, character ; needs to be escaped
Yes, character < needs to be escaped
Yes, character > needs to be escaped
Yes, character ? needs to be escaped
Yes, character [ needs to be escaped
Yes, character \ needs to be escaped
Yes, character ] needs to be escaped
Yes, character ^ needs to be escaped
Yes, character ` needs to be escaped
Yes, character { needs to be escaped
Yes, character | needs to be escaped
Yes, character } needs to be escaped
有些结果,看起来有点可疑。获得@CharlesDuffy在这方面的投入会很有趣。
我猜你说的是bash字符串。有不同类型的字符串,它们对转义有不同的要求。如。单引号字符串不同于双引号字符串。
最好的参考是bash手册的引用部分。
它解释了哪些字符需要转义。注意,某些字符可能需要转义,这取决于启用了哪些选项,如历史扩展。
我注意到bash在使用自动完成时自动转义一些字符。
例如,如果你有一个名为dir: a的目录,bash会自动补全到dir\: a
使用这个,我运行了一些实验,使用ASCII表的字符,并推导出以下列表:
bash自动完成转义的字符:(包括空格)
!"$&'()*,:;<=>?@[\]^`{|}
bash没有转义的字符:
#%+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~
(我排除了/,因为它不能在目录名中使用)
为了不让别人不得不RTFM…在bash中:
用双引号括起来的字符会保留引号内所有字符的文字值,除了$、'、\和(当启用历史扩展时)!
...所以如果你转义了这些(当然还有引用本身),你可能就没事了。
如果你采取更保守的“当有疑问时,转义它”的方法,应该可以通过不转义标识符字符(即ASCII字母、数字或“_”)来避免获得具有特殊含义的字符。这是非常不可能的(即在一些奇怪的posix shell中)有特殊的含义,因此需要转义。