现象重现
在编写Shell脚本时,我们经常遇到这样的场景:
Result=$((time wget --spider http://www.baidu.com/) 2>&1 | grep -E 'real|response')
echo "$Result" # 保持换行格式
echo $Result # 输出变成单行
底层机制解析
这种差异源于Bash的单词分割(Word Splitting)机制:
- 使用双引号时:"$variable"会保留原始字符串的所有空白字符(包括换行符)
- 无引号时:Bash会按照IFS(Internal Field Separator)默认值(空格/tab/换行)进行分割
实际开发中的影响
在以下场景需要特别注意:
# 处理多行日志时
log_data="Error 500\nat main.js:15\nTimestamp: $(date)"
echo $log_data # 会丢失关键格式信息
最佳实践建议
根据阿里巴巴《Shell脚本开发规范》建议:
- 总是用引号包裹变量引用
- 处理多行文本时使用heredoc
- 需要保留空白字符时使用数组
# 推荐写法
echo "${Result}"
# 处理包含特殊字符的情况
printf "%s\n" "$Result"
扩展场景测试
我们通过更多案例验证这个特性:
# 测试1:包含空格的路径
path="/tmp/my docs"
ls $path # 会报错
ls "$path" # 正常执行
# 测试2:JSON数据处理
json='{"name":"张三","age":25}'
echo $json | jq . # 会解析失败
echo "$json" | jq . # 正常解析