引用指将字符串用引用符号括起来,以防止特殊字符被Shell脚本重解释为其他意义,特殊字符是指除了字面意思之外还可以解释为其他意思的字符
📝 Shell引号符号完全详解
一、三种引号的核心区别
| 符号 | 名称 | 核心作用 | 是否解析变量 | 是否解析命令 | 是否解析转义 |
|---|
| ” “ | 双引号 | 弱引用 | ✅ 是 | ✅ 是 | ✅ 大部分 |
| ‘ ‘ | 单引号 | 强引用 | ❌ 否 | ❌ 否 | ❌ 完全禁止 |
| “ | 反引号 | 命令替换 | ✅ 是 | ✅ 执行命令 | ✅ 是 |
| ** | 反斜线 | 转义符 | 屏蔽下一个字符的特殊意义 | | |
二、双引号 " " 详解
2.1 基本特性
# 双引号会解析变量、命令和部分转义
name="Tom"
echo "Hello $name" # Hello Tom(解析变量)
echo "Today is `date`" # Today is 2024...(执行命令)
echo "Line1\nLine2" # 可能解析\n(取决于echo版本)
2.2 保留特殊含义的字符
# 双引号内仍生效的符号
echo "$HOME" # 解析变量 $
echo "`date`" # 执行命令 ``
echo "\\" # 转义符 \ 仍有效
echo "\$HOME" # 输出 $HOME(\$转义了$)
2.3 失去特殊含义的字符
# 双引号内失去特殊含义
echo "*" # 输出 *,不是通配符
echo "?" # 输出 ?,不是通配符
echo "[a-z]" # 输出 [a-z],不是字符集
echo ";" # 输出 ;,不是命令分隔符
三、单引号 ' ' 详解
3.1 最强引用——所见即所得
# 单引号内所有字符都是字面意思
name="Tom"
echo 'Hello $name' # Hello $name(不解析变量)
echo 'Today is `date`' # Today is `date`(不执行命令)
echo 'Line1\nLine2' # Line1\nLine2(不解析转义)
3.2 单引号内唯一不能包含的是单引号本身
# 单引号内不能有单引号
echo 'It\'s Tom' # 错误!语法错误
echo 'It'\''s Tom' # 正确:用转义方式
echo "It's Tom" # 简单:用双引号
3.3 单引号的实际应用
# 场景1:包含大量特殊字符
echo '!@#$%^&*()_+{}[]:;"<>?,./'
# 场景2:正则表达式
grep '^[a-z]*$' file.txt
# 场景3:别名定义
alias ll='ls -la --color=auto'
# 场景4:不希望变量展开
password='$2y$10$...' # 包含$符号的密码
四、反引号 ` ` 详解
4.1 命令替换的基本用法
# 将命令输出赋值给变量
current_date=`date`
echo $current_date # 2024-01-15 10:30:00
# 直接嵌入字符串
echo "Today is `date +%A`" # Today is Monday
# 嵌套使用
files_count=`ls | wc -l`
echo "文件数量: $files_count"
4.2 反引号 vs $() 对比
# 反引号(旧式)
date=`date`
files=`ls -la`
# $()(新式,推荐)
date=$(date)
files=$(ls -la)
# 嵌套命令的对比
# 反引号嵌套需要转义
dirs=`ls -ld \`find . -type d\` | wc -l`
# $()嵌套更清晰
dirs=$(ls -ld $(find . -type d) | wc -l)
4.3 实际应用场景
# 获取进程PID
pid=`ps aux | grep nginx | grep -v grep | awk '{print $2}'`
# 动态文件名
backup_file="backup_`date +%Y%m%d_%H%M%S`.tar.gz"
# 数学计算
result=`expr 5 + 3`
# 组合命令
echo "当前登录用户: `who | wc -l`"
五、反斜线 \ 详解
5.1 转义特殊字符
# 让特殊字符回归字面意思
echo \$HOME # 输出 $HOME(不解析变量)
echo \* # 输出 *(不是通配符)
echo \\ # 输出 \(转义自身)
echo \`date\` # 输出 `date`(不执行命令)
5.2 常用转义序列
# 换行和空格
echo line1 \
line2 # 续行符
# 转义特殊字符
echo "It\'s Tom" # It's Tom(在双引号中)
echo It\'s Tom # It's Tom(不在引号中)
# 表示特殊控制字符
echo -e "Line1\nLine2" # \n 换行(需要-e)
echo -e "Col1\tCol2" # \t 制表符
5.3 在引号中的表现
# 双引号中:大部分转义有效
echo "\$HOME" # $HOME
echo "\\" # \
echo "\`date\`" # `date`
# 单引号中:转义无效
echo '\$HOME' # \$HOME(原样输出)
echo '\\' # \\
六、四种符号的综合对比
6.1 作用范围对比表
| 符号 | 变量$ | 命令“ | 转义\ | 通配符*? | 空格 | 适用场景 |
|---|
| 无引号 | 解析 | 解析 | 解析 | 解析 | 分隔符 | 简单命令 |
| ” “ | 解析 | 解析 | 解析 | 不解析 | 保留 | 需要变量/命令的字符串 |
| ‘ ‘ | 不解析 | 不解析 | 不解析 | 不解析 | 保留 | 纯字面字符串 |
| “ | 解析 | 执行 | 解析 | 解析 | 保留 | 命令替换 |
6.2 实际应用示例
# 场景1:文件名带空格
file="my file.txt"
cat "$file" # 正确,保留空格
cat $file # 错误,变成两个参数
# 场景2:变量拼接
prefix="log"
echo "${prefix}_2024.txt" # log_2024.txt(推荐)
echo $prefix_2024.txt # 错误,变量名变成prefix_2024
# 场景3:复杂命令
result=$(grep "error" $(find logs -name "*.log"))
# 场景4:多行文本
message='
This is a multi-line
text with "quotes" and $variables
that should be literal
'
echo "$message"
# 场景5:正则表达式
grep '^[0-9]\{3\}-[0-9]\{4\}$' phones.txt
七、常见错误与最佳实践
7.1 常见错误
# 错误1:变量未加引号
file="my document.txt"
cat $file # 错误!试图cat两个文件
# 错误2:单引号内使用变量
echo 'Current user: $USER' # 输出 $USER,不是变量值
# 错误3:反引号嵌套混乱
files=`ls -l `find . -name "*.txt"`` # 混乱
# 错误4:忘记转义特殊字符
echo "Path: $PATH" # 正确
echo "Path: \$PATH" # 如果你想输出 $PATH 字面
7.2 最佳实践
# 1. 变量引用永远加双引号
echo "$filename"
rm -f "$file"
# 2. 字面字符串用单引号
grep '^#.*$' config.txt
# 3. 命令替换用 $() 代替反引号
files=$(ls -la)
# 4. 变量拼接用 ${var}
echo "${base}_${date}.${ext}"
# 5. 多参数用数组
args=("$@")
for arg in "${args[@]}"; do
echo "$arg"
done
八、快速记忆口诀
双引号弱引用,变量命令仍生效
单引号强引用,所见即所得最牢
反引号执行令,结果替换内容中
反斜线转义符,屏蔽特殊显神通
无引号最危险,空格切分通配展
变量要安全,双引号包起来最保险
字面要原样,单引号包裹最稳当
命令要结果,$()写法最清爽
✅ 总结
| 符号 | 一句话记忆 |
|---|
| ” “ | 变量解析,通配不解析,空格保留 |
| ‘ ‘ | 所有字符原样输出,最严格 |
| “ | 执行命令,替换输出(旧式) |
| $( ) | 执行命令,替换输出(新式,推荐) |
| ** | 让下一个字符失去特殊意义 |
发表回复