为什么我不能在 bash 的引号中生成换行符?
Why can't I generate newlines in quotes in bash?
无论我做什么,我都无法让引号中的换行符保留在输出中。我是什么做的?这是 OS X 中的 bash。我的代码在这里:Gist
read -d '' sbt_text=$(cat <<"EOF"
#!/bin/bash
SBT_OPTS="-Xms512M -Xmx1536M -Xss1M -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=256M";
java $SBT_OPTS -jar `dirname [=11=]`/sbt-launch.jar "$@"
EOF
)
echo $sbt_text
#!/bin/bash > SBT_OPTS="-Xms512M -Xmx1536M -Xss1M -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=256M"; > java -jar /sbt-launch.jar ""
你应该引用你的变量:
echo "$sbt_text"
这可以防止 Bash 进行 单词拆分 (和 通配符 ,即扩展通配符,例如 *
和 ?
) 在替换你的变量(参数扩展)之后。请注意,为 read
设置 IFS
不会阻止 echo
命令行上的分词。试试这个好玩的:
( IFS= ; echo $sbt_text )
对比
IFS= echo $sbt_text ### won't work
第二个示例将不起作用 - subshell (( )
) 在这里是必需的,因为 IFS
被调用 shell 解释为相反的分词在问题的代码示例中被 read
解释。
当然这也有效(但是 "ruins" 你的 IFS
):
IFS= ; echo $sbt_text
你可能想要的是:
IFS= read -d '' -r sbt_text <<"EOF"
#!/bin/bash
SBT_OPTS="-Xms512M -Xmx1536M -Xss1M -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=256M";
java $SBT_OPTS -jar `dirname [=10=]`/sbt-launch.jar "$@"
EOF
echo "$sbt_text"
虽然您的 read
命令无法像发布的那样工作,但 不使用双引号 $sbt_text
将始终执行 word splitting (and also pathname expansion (globbing)),当传递给 echo
时,意味着任何内部白色 space 都标准化为 单个 space .
为了在 POSIX-like shell 中保持变量 原样 的值 - 不对其进行处理对于上面描述的 shell expansions - 你必须 双引号 它。
关于read
命令,注意:
-r
可防止对输入中的 \
个实例进行通常无意的解释。
- 前置
IFS=
确保此处文档中的每一行相对于白色 space 保持原样(不修剪前导和尾随白色 space)
- 不需要 command substitution (
$(...)
) with cat
, because <<
(a here-document) 直接提供 stdin 输入,read
从中获取输入。
- 通过在您的
read
命令中使用 sbt_text=$(...)
,您实际上将命令替换 ($(...)
) 的输出作为(最终无效的)变量的一部分name 而不是提供 input,导致 read
仍然等待 stdin 输入。
- 使用just赋值
sbt_text=$(cat <<"EOF" ...)
(没有read
)几乎可以给你你想要的东西(尽管以调用外部实用程序为代价cat
), 除了命令替换会删除任何尾随的换行符。
无论我做什么,我都无法让引号中的换行符保留在输出中。我是什么做的?这是 OS X 中的 bash。我的代码在这里:Gist
read -d '' sbt_text=$(cat <<"EOF"
#!/bin/bash
SBT_OPTS="-Xms512M -Xmx1536M -Xss1M -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=256M";
java $SBT_OPTS -jar `dirname [=11=]`/sbt-launch.jar "$@"
EOF
)
echo $sbt_text
#!/bin/bash > SBT_OPTS="-Xms512M -Xmx1536M -Xss1M -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=256M"; > java -jar /sbt-launch.jar ""
你应该引用你的变量:
echo "$sbt_text"
这可以防止 Bash 进行 单词拆分 (和 通配符 ,即扩展通配符,例如 *
和 ?
) 在替换你的变量(参数扩展)之后。请注意,为 read
设置 IFS
不会阻止 echo
命令行上的分词。试试这个好玩的:
( IFS= ; echo $sbt_text )
对比
IFS= echo $sbt_text ### won't work
第二个示例将不起作用 - subshell (( )
) 在这里是必需的,因为 IFS
被调用 shell 解释为相反的分词在问题的代码示例中被 read
解释。
当然这也有效(但是 "ruins" 你的 IFS
):
IFS= ; echo $sbt_text
你可能想要的是:
IFS= read -d '' -r sbt_text <<"EOF"
#!/bin/bash
SBT_OPTS="-Xms512M -Xmx1536M -Xss1M -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=256M";
java $SBT_OPTS -jar `dirname [=10=]`/sbt-launch.jar "$@"
EOF
echo "$sbt_text"
虽然您的 read
命令无法像发布的那样工作,但 不使用双引号 $sbt_text
将始终执行 word splitting (and also pathname expansion (globbing)),当传递给 echo
时,意味着任何内部白色 space 都标准化为 单个 space .
为了在 POSIX-like shell 中保持变量 原样 的值 - 不对其进行处理对于上面描述的 shell expansions - 你必须 双引号 它。
关于read
命令,注意:
-r
可防止对输入中的\
个实例进行通常无意的解释。- 前置
IFS=
确保此处文档中的每一行相对于白色 space 保持原样(不修剪前导和尾随白色 space) - 不需要 command substitution (
$(...)
) withcat
, because<<
(a here-document) 直接提供 stdin 输入,read
从中获取输入。- 通过在您的
read
命令中使用sbt_text=$(...)
,您实际上将命令替换 ($(...)
) 的输出作为(最终无效的)变量的一部分name 而不是提供 input,导致read
仍然等待 stdin 输入。 - 使用just赋值
sbt_text=$(cat <<"EOF" ...)
(没有read
)几乎可以给你你想要的东西(尽管以调用外部实用程序为代价cat
), 除了命令替换会删除任何尾随的换行符。
- 通过在您的