在子shell中运行的heredocs中保留反斜杠换行符

在子shell中运行的heredocs中保留反斜杠换行符

只要终端反斜杠不存在,在捕获变量中的heredoc的输出后,就会保留heredoc的换行符:

var=$(cat <<-EOF
a
b
c
EOF
)
echo "$var"

a
b
c

然而,当尝试存储反斜杠换行符时,换行符会丢失:

var=$(cat <<-EOF
a \\
b \\
c
EOF
)

echo "$var"
a \b \c

添加额外的反斜杠以进一步转义并没有帮助。

当然,当不在子 shell 中运行时,heredoc 可用于生成以反斜杠换行符结尾的行:

$ cat <<-EOF
a \\
b \\
c
EOF
a \
b \
c

为了避免这个问题,可以添加一个换行符来通过变量的转换生成所需的输出:

var=$(cat <<-EOF
a \\@
b \\@
c
EOF
)

tr -d '@' <<<"$var"

a \
b \
c

是否有更直接的方法来保留在子 shell 中运行的heredocs 中的反斜杠换行符?

答案1

我想知道这是否是 Bash 中的一个错误(或者反斜杠换行符的行为是否只是未定义)。我尝试过的所有其他 shell 都表现出与 Bash 不同的行为:

$ cat nl.sh

echo "1:"
cat <<EOF
a \\
b \\
c
EOF

echo "2:"
var=$(cat <<-EOF
a \\
b \\
c
EOF
)
echo "$var"

输出:

$ bash nl.sh
1:
a \
b \
c
2:
a \b \c

$ dash nl.sh
1:
a \
b \
c
2:
a \
b \
c

您可以将代码放入函数的命令替换中,这可能有助于解决解析器的任何问题,例如:

f() {
cat <<EOF
a \\
b
EOF
}
var=$(f)
echo "$var"

答案2

没有直接的方法可以使换行符在此处文档内强制扩展。但是您可以使用包含使用 ANSI 转义序列 ( ) 编码的换行符的变量$'\n',并使变量扩展发生在定界文档内。

请注意,这种形式的异教扩展需要将您的分隔'EOF'符不加引号,即如下所示,

nl=$'\n'

并使用该$nl变量作为换行符的占位符

var=$(cat <<-EOF
a $nl
b $nl
c
EOF
)

现在可以正确发出

echo "$var"
a 

b 

c

相关内容