哪些字符需要在Bash中转义? 我们怎么知道它?

是否有需要在Bash中转义的字符的全面列表? 可以用sed检查吗?

特别是,我正在检查是否需要转义% 。 我试过了

 echo "h%h" | sed 's/%/i/g' 

并工作得很好,没有逃脱% 。 这是否意味着%不需要被转义? 这是检查必要性的好方法吗?

而更一般的:他们是相同的字符在shellbash逃脱吗?

有两个简单而安全的规则,不仅适用于sh ,也适用于bash

1.把整个string放在单引号中

这适用于除单引号之外的所有字符。 要转义单引号,请先closures引号,插入单引号,然后重新打开引号。

 'I'\''mas@fe $tring which ends in newline ' 

sed命令: sed -e "s/'/'\\\\''/g; 1s/^/'/; \$s/\$/'/"

2.用反斜杠将每个字符都转义出来

这适用于除了换行符之外的所有字符。 换行符使用单引号或双引号。 必须仍然处理空string – 用""replace

 \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/$/"/' sed -e 's/./\\&/g; 1{$s/^$/""/}; 1!s/^/"/; $!s/$/"/' 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/$/"/' LC_ALL=C sed -e 's/[^a-zA-Z0-9,._+@%/-]/\\&/g; 1{$s/^$/""/}; 1!s/^/"/; $!s/$/"/' LC_ALL=C sed -e 's/[^a-zA-Z0-9,._+@%/-]/\\&/g; 1{$s/^$/""/}; 1!s/^/"/; $!s/$/"/'


请注意,在sed程序中,不能确定最后一行input是否以换行符结束(除非是空的)。 这就是为什么上面的sed命令都假设没有。 您可以手动添加带引号的换行符。

请注意,shellvariables只是为POSIX意义上的文本定义的。 处理二进制数据没有定义。 对于那些重要的实现,除了NUL字节之外,二进制文件是可以工作的(因为variables是用Cstring实现的,并且用作Cstring,也就是程序参数),但是你应该切换到一个“二进制”的语言环境,例如latin1 。


(您可以通过阅读sh的POSIX规范来轻松validation规则。对于bash,请查看@AustinPhillips链接的参考手册)

要保存其他人从RTFM …在bash中

用双引号括起来的字符保留了引号中所有字符的字面值,除了$`\ ,并且当启用历史扩展时, !

…所以,如果你逃避了这些(当然还有引用本身),你可能没问题。

如果采取更加保守的“有疑问,逃避”的方法,应该可以通过不转义标识符字符(即ASCII字母,数字或'_')来避免取得具有特殊含义的字符。 这是不太可能的(即在一些奇怪的POSIX-ishshell中)具有特殊的含义,因此需要逃脱。

在Bourne或POSIX shell中,需要转义的字符与Bash不同。 一般来说(非常)Bash是这些炮弹的超集,所以你在shell中逃跑的任何东西都应该在Bash中逃脱。

一个很好的通用规则是“如果有疑问,逃避它”。 但是逃脱某些angular色给了他们一个特殊的含义,比如\n 。 这些被列在Quotingecho下的man bash页面中。

除此之外,逃避任何不是字母数字的字符,更安全。 我不知道一个确切的清单。

手册页列出所有的地方,但不在一个地方。 学习语言,这是可以肯定的。

一个让我出去的是! 。 这是Bash(和csh)中的一个特殊字符(历史扩展),但不是在Korn shell中。 甚至echo "Hello world!" 给出问题。 像往常一样使用单引号,删除了特殊的含义。

格式,可以重新用作shellinput

为这种请求构build了一个特殊的 printf格式指令( %q ):

printf [-v var]格式[参数]

  %q causes printf to output the corresponding argument in a format that can be reused as shell input. 

一些样品:

 read foo Hello world printf "%q\n" "$foo" Hello\ world printf "%q\n" $'Hello world!\n' $'Hello world!\n' 

这也可以通过variables来使用:

 printf -v var "%q" "$foo " echo "$var" $'Hello world\n' 

我假定你在讨论bashstring。 有不同types的string有不同的转义要求。 例如。 单引号string与双引号string不同。

最好的参考是bash手册的引用部分。

它解释了哪些字符需要转义。 请注意,某些字符可能需要转义,具体取决于启用了哪些选项,如历史扩展。

我注意到,使用自动完成时,bash会自动转义一些字符。

例如,如果您有一个名为dir:A的目录,bash将自动完成到dir\:A

使用这个,我跑了一些使用ASCII表格的字符的实验,并得出以下列表:

bash在自动完成时逃脱的字符 :(包括空格)

  !"$&'()*,:;<=>?@[\]^`{|} 

bash不能逃脱的字符

 #%+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~ 

(我排除/ ,因为它不能在目录名称中使用)

使用print '%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的投入。