SSH远程执行Bash脚本时sed命令无法正常添加\n的问题求助
问题原因
- 核心是Here文档的转义解析层级问题:你当前使用的是未加引号的分界符
<< EOF,本地Shell会提前对Here文档内的转义字符、变量做展开处理。你代码里写的sed 's/$/\\n/'中的\\n会被本地Shell先解析为\n,最终传到远程机器执行的命令实际是sed 's/$/\n/',你之前尝试给匹配规则里的$添加转义没有效果,是因为问题根源并不是行尾匹配符$被解析,而是替换字符串部分的\n转义层级不符合预期。 - 其次是sed的实现差异:非GNU版本的sed(比如BSD系系统、macOS默认自带的sed)不支持在替换字符串中直接用
\n表示换行符,也会导致添加换行的逻辑失效。
解决方案
你可以任选以下一种方案修复:
- 给Here文档的分界符加单引号,禁用本地Shell的提前展开,所有命令会原样传到远程执行,只要远程环境是GNU sed就能直接正常运行:
set -e set -o pipefail ssh "$host" << 'EOF' temp_working_dir=/tmp/working_dir mycert_path=${temp_working_dir}/mycert/ cert=$(cat "${mycert_path}"/cert.pem | sed 's/$/\\n/' | tr -d '\n') echo "$cert" > /tmp/cert EOF
- 保留当前未加引号的Here文档写法,加多一层转义,把
\\n改为\\\\n,确保本地解析后传到远程的仍然是\\n:
cert=\$(cat "\${mycert_path}"/cert.pem | sed 's/$/\\\\n/' | tr -d '\n')
- 使用兼容所有POSIX环境的awk实现,不用考虑不同sed的实现差异,稳定性更高:
cert=\$(awk '{printf "%s\\n", \$0}' "\${mycert_path}/cert.pem" | tr -d '\n')
内容的提问来源于stack exchange,提问作者Madhu CM
相关产品推荐
相关产品推荐

