Bash拼接含换行符的字符串变量时丢失换行的问题
问题根源
命令替换$(...)会自动丢弃输出末尾的换行符,这是你遇到问题的核心。
你定义变量的命令:
A="$(echo 33; echo 44)"
echo 33; echo 44的实际输出是33\n44\n(两个换行),但经过$(...)捕获后,末尾的换行被自动去掉了——所以变量A的真实内容是33\n44(只有一个换行,没有末尾的换行)。
第一次执行echo "$A"时,echo会自动在输出末尾补一个换行,所以hexdump里看到的最后一个0a是echo加的,不是A本身的内容。当你拼接55后,A变成33\n4455,echo "$A"依然只补一个末尾换行,最终输出就是33\n4455\n,对应两行内容。
解决办法
要实现拼接后输出3行(即最终内容为33\n44\n55\n),可以用以下几种方案:
方案1:定义变量时保留末尾换行
在命令替换的输出末尾额外加一个换行,利用命令替换只删最后一个换行的特性,让变量保留末尾的换行:
# 多输出一个空行,命令替换去掉最后一个换行后,A就保留了33\n44\n A="$(echo 33; echo 44; echo)"
再拼接55:
A="$A""55"
此时A的内容是33\n44\n55,执行echo "$A"时,echo补一个末尾换行,最终输出3行。
或者用更可靠的参数替换技巧:
# 用printf x占位,之后去掉x,确保保留末尾换行 A="$(echo 33; echo 44; printf x)" && A="${A%x}"
方案2:拼接时手动添加换行
如果不想修改原变量定义,拼接55时直接在前面加换行($'\n'是bash的ANSI-C转义,代表换行符):
A="$A"$'\n'"55"
此时A的内容变为33\n44\n55,echo "$A"会输出3行。
方案3:用printf输出替代echo
如果只是要输出3行,不用修改变量,直接用printf控制输出格式,避免echo自动补换行的影响:
printf "%s\n55\n" "$A"
这个命令会直接输出33\n44\n55\n,对应3行内容。
内容的提问来源于stack exchange,提问作者Robin Hsu
相关产品推荐
相关产品推荐

