首页/开发/正则与编码速查/Shell 引号与转义层叠问题

Shell 引号与转义层叠问题

Shell 转义的关键是分清「Shell 层」与「命令层」两级解释:单引号全字面量、双引号仍展开变量与命令替换、$'...' 提供控制字符、here-doc 用带引号的定界符关闭展开。传参一律用 "$var",不要拼接外部输入再执行。

正则与编码速查开发更新于 2026-10-17
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌​​‌​‌‌‌‌​‌‌‌​​‌​​‌‌​​‌​‌​‌‌​​‌‌‌​‌‌​​‌​‌​‌‌‌‌​​​​​‌​‌‌‌‌​‌‌‌​​‌‌​‌‌​‌​​​​‌‌​​‌​‌​‌‌​‌‌​​​‌‌​‌‌​​​​‌​‌‌​‌​‌‌‌​​​‌​‌‌‌​‌​‌​‌‌​‌‌‌‌​‌‌‌​‌​​​‌‌​​‌​‌​​‌​‌‌​‌​‌‌​​‌​‌​‌‌‌​​‌‌​‌‌​​​‌‌​‌‌​​​​‌​‌‌‌​​​​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​​‌​‌‌‌​​‌‌​‌​​​​‌‌‌​‌​​​‌‌​‌‌​‌​‌‌​‌‌​​

引号决定谁先解释字符

Shell 转义的本质是分层:Shell 先解释一层,命令自己再解释一层。单引号里除单引号本身外一切原样,双引号里美元符号、反引号、反斜杠与感叹号仍有含义,反斜杠则让紧随的一个字符失去特殊含义。写正则、JSON、sed 表达式这类本身就带转义的内容时,必须先想清楚哪一层负责解释哪个反斜杠。

基本信息

适用环境POSIX shell、bash、dash、zsh;PowerShell 规则不同
单引号内部全字面量,无法在内部再转义单引号
双引号仍会做变量展开、命令替换、反斜杠转义
ANSI-C 引号$'...' 可写 \n、\t、\xHH、\uXXXX,属 bash/zsh 扩展
多行文本here-doc 用加引号的定界符关闭展开,适合粘贴脚本与 JSON

典型使用场景

  • 把含空格、括号的文件名传给命令,避免被拆词或当通配符展开
  • 写 sed、awk 或 grep 的正则表达式,处理反斜杠翻倍
  • 在脚本里嵌入一段 JSON 或 SQL,用 here-doc 保留原文
  • 远程执行:ssh host 'cmd' 里再套一层引号,需要确认哪层剥壳
  • 日志与审计:用 printf 打印变量原值,避免格式串被变量污染

分层写法示例

分层写法示例
echo "$name"                     # 变量值按原样传出,不做拆词
printf '%s\n' "$raw"              # 打印任意内容,格式串与数据分离
regex='^[0-9]{3}-[0-9]{4}$'       # 正则用单引号包住,Shell 不动它
grep -E "$regex" app.log          # 传给 grep 的正则只解释一层
cat <<'EOF' > conf.json           # 定界符加引号,正文不展开、原样落盘
{"path": "C:\\data", "user": "$HOME"}
EOF
ssh host 'cd /srv/app && ls'      # 整条远端命令作为一个参数

引号行为对照

写法变量展开路径通配典型用途
$var展开并拆词会展开几乎总是不该这么写
"$var"展开不拆词不展开传参默认选择
'$var'不展开不展开正则、JSON、字面量
$'...'不展开不展开需要 \n、\t 等控制字符
<<'EOF'不展开不展开多行原文输入
单引号内不能直接转义单引号,标准写法是关闭字符串、插入转义引号、再打开:'it'\''s'。这在拼接提交信息或 SQL 字面量时经常用到。
不要用双引号把外部输入拼成命令再交给 eval、sh -c 或数据库客户端,变量里带的分号与反引号会变成命令。需要构造命令时用数组或位置参数传值,而不是拼字符串。

易错点

  • 变量不加双引号:含空格的文件名被拆成多个参数,含通配符的还会被展开;rm -rf "$dir/" 与 rm -rf "$dir" 的语义差异就是这类事故的典型
  • 在单引号里写 \' 以为能转义,实际是结束字符串后跟一个普通字符,命令结构被破坏
  • 跨层引用引号没对齐:ssh host "cmd 'arg'" 与 ssh host 'cmd "arg"' 剥掉的层不同,远端拿到的参数也不一样
  • PowerShell 与 bash 习惯混用:PowerShell 的转义符是反引号,把 bash 写法直接搬过去会得到转义失效或参数丢失
  • 把正则直接放进双引号,其中的 $ 被当变量、反引号被当命令替换,grep 拿到的模式已不是原意

数据来源与参考

  • POSIX.1-2017:Shell Command Language 的 Quoting 章节
  • GNU Bash 参考手册:Quoting 与 ANSI-C Quoting
  • Microsoft Learn:about_Quoting_Rules(PowerShell)

整理校对:其其网ICT文档中心 · 本页地址:docs.qiqicto.com/regex/shell-quote-escaping.html

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌​​‌​‌‌‌‌​‌‌‌​​‌​​‌‌​​‌​‌​‌‌​​‌‌‌​‌‌​​‌​‌​‌‌‌‌​​​​​‌​‌‌‌‌​‌‌‌​​‌‌​‌‌​‌​​​​‌‌​​‌​‌​‌‌​‌‌​​​‌‌​‌‌​​​​‌​‌‌​‌​‌‌‌​​​‌​‌‌‌​‌​‌​‌‌​‌‌‌‌​‌‌‌​‌​​​‌‌​​‌​‌​​‌​‌‌​‌​‌‌​​‌​‌​‌‌‌​​‌‌​‌‌​​​‌‌​‌‌​​​​‌​‌‌‌​​​​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​​‌​‌‌‌​​‌‌​‌​​​​‌‌‌​‌​​​‌‌​‌‌​‌​‌‌​‌‌​​