UNIX下echo命令输出多变量时仅显示最后一个值的问题
问题现象
- 定义
var1、var2两个Shell变量后,执行echo $var1$var2命令输出变量拼接结果时,终端仅显示var2的取值 - 拼接3个及以上变量执行同类echo输出操作时,终端始终仅显示最后一个变量的取值
问题根因
该异常由**变量值中混入回车符(\r,即Carriage Return字符)**导致。
这类问题最常见的诱因是脚本跨系统编辑:Windows系统默认的行尾格式为\r\n(CRLF),而UNIX/Linux系统默认识别的行尾格式为\n(LF),如果在Windows上编辑Shell脚本后直接传到UNIX环境运行,每一行末尾的\r会被Shell识别为变量值的一部分存入对应变量。
当你执行拼接输出时,\r的作用是将光标移动回当前行的起始位置,后续输出的内容会从行首开始覆盖之前已经打印的内容:比如var1实际存储值为foo\r,var2存储值为bar,执行echo $var1$var2时,终端先打印foo,遇到\r后光标回到行首,接着打印bar就会把前面的foo完全覆盖,视觉上就像只输出了var2的值。拼接变量越多,前面输出的内容被后续内容依次覆盖,最终就只会留下最后一个变量的显示结果。
排查方法
- 执行
od -c 你的脚本文件路径查看脚本的实际字节内容,如果发现行尾标记为\r\n而非单独的\n,即可确认是行尾格式问题 - 可以给单个变量的输出前后加固定标记验证,比如执行
echo "start:${var1}:end",如果输出结果中end或者后续内容跑到了行首位置、覆盖了start标记,就说明对应变量中混入了\r字符
解决方案
- 修复存量CRLF格式脚本:
- 可直接安装
dos2unix工具,执行dos2unix 你的脚本文件路径一键完成行尾格式转换,自动删除所有行尾多余的\r - 没有安装
dos2unix的环境下,可直接用sed命令批量替换:sed -i 's/\r$//' 你的脚本文件路径
- 可直接安装
- 动态处理带
\r的变量:如果变量是运行时动态生成、而非从脚本读入的,可以在赋值后用Bash内置字符串处理能力删除其中的\r字符,示例:var1=${var1//$'\r'/} - 源头规避:日常编写Shell脚本时,尽量直接在UNIX环境下编辑;如果必须在Windows上编辑,提前将编辑器的默认行尾格式切换为LF(VS Code、Notepad++等常用编辑器都可在底部状态栏快速切换行尾格式),避免写入多余的回车字符。
内容的提问来源于stack exchange,提问作者Mohak
相关产品推荐
相关产品推荐

