在命令行参数中需要转义哪些字符?

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(空格)

其中一些字符比我链接的字符用于更多的事情和更多的地方。


有一些极端情况是明确可选的:


转义换行符需要引用——反斜杠不起作用。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,则您是安全的(目前)。

  • 引用内置函数、破折号或 % 没有任何作用。 (2认同)