Tim*_*Tim 21 shell bash quoting
在 Bash 中,当为命令指定命令行参数时,需要转义哪些字符?
它们是否仅限于 Bash 的元字符:空格、制表符
|、&、;、(、)、<、 和>?
Mic*_*mer 28
以下字符在某些上下文中对 shell 本身具有特殊含义,可能需要在参数中进行转义:
| 特点 | 统一码 | 姓名 | 用法 |
|---|---|---|---|
` |
U+0060(重口音) | 反引号 | 命令替换 |
~ |
U+007E | 波浪号 | 波浪号扩展 |
! |
U+0021 | 感叹号 | 历史扩展 |
# |
U+0023 数字符号 | 哈希 | 注释 |
$ |
U+0024 | 美元符号 | 参数扩展 |
& |
U+0026 | 与号 | 后台命令 |
* |
U+002A | 星号 | 文件名扩展和通配 |
( |
U+0028 | 左括号 | 子壳 |
) |
U+0029 | 右括号 | 子壳 |
|
U+0009 | 标签?( ?) |
分词(空格) |
{ |
U+007B 左花括号 | 左大括号 | 支撑扩展 |
[ |
U+005B | 左方括号 | 文件名扩展和通配 |
| |
U+007C 竖线 | 竖条 | 管道 |
\ |
U+005C 反向固相线 | 反斜杠 | 转义字符 |
; |
U+003B | 分号 | 分隔命令 |
' |
U+0027 撇号 | 单引号 | 字符串引用 |
" |
U+0022 引号 | 双引号 | 带插值的字符串引用 |
? |
U+000A 换行 | 新队 | 越线 |
< |
U+003C | 少于 | 输入重定向 |
> |
U+003E | 比...更棒 | 输出重定向 |
? |
U+003F | 问号 | 文件名扩展和通配 |
? |
U+0020 | 空间 | 分词1(空格) |
其中一些字符比我链接的字符用于更多的事情和更多的地方。
有一些极端情况是明确可选的:
!可以使用 禁用set +H,这是非交互式 shell 中的默认设置。{可以禁用set +B。*并且?可以使用set -f或set -o noglob禁用。=如果启用set -k或 ,set -o keyword也需要转义等号 (U+003D) 。转义换行符需要引用——反斜杠不起作用。IFS 中列出的任何其他字符都需要类似的处理。您不需要转义]or },但您确实需要转义,)因为它是一个运算符。
其中一些角色对何时真正需要逃离的限制比其他角色更严格。例如,a#b可以,但是a #b是注释,而>在这两种情况下都需要转义。无论如何,保守地避开它们并没有什么坏处,而且比记住细微的区别更容易。
如果您的命令名称本身是一个 shell 关键字(if, for, do),那么您也需要转义或引用它。其中唯一有趣的是in,因为它始终是关键字并不明显。你并不需要做的是在辩论中使用的关键词,只有当你(愚蠢!)其中一人的名字命名的命令。Shell 操作符((、&等)总是需要引用它们所在的位置。
1 Stéphane 指出,来自您的语言环境的任何其他单字节空白字符也需要转义。在最常见的、合理的语言环境中,至少是基于 C 或 UTF-8 的语言环境,它只是上面的空白字符。在某些 ISO-8859-1 语言环境中,U+00A0 不间断空格被视为空白,包括 Solaris、BSD 和 OS X(我认为是错误的)。如果您正在处理任意未知的语言环境,它可能包括任何内容,包括字母,祝您好运。
可以想象,被认为是空白的单个字节可能出现在非空白的多字节字符中,除了将整个内容放在引号中之外,您无法逃避它。这不是理论上的问题:在上面的 ISO-8859-1 语言环境中A0,被视为空白的字节可以出现在多字节字符中,例如 UTF-8 编码的“à”( C3 A0)。要安全地处理这些字符,您需要引用它们"à"。此行为取决于运行脚本的环境中的语言环境配置,而不是您编写脚本的环境。
我认为这种行为在很多方面都被打破了,但我们必须玩我们被处理的那手牌。如果您正在使用任何非自同步多字节字符集,最安全的做法是引用所有内容。如果您使用 UTF-8 或 C,则您是安全的(目前)。