如何在 sh 的字符串中添加换行符?
这
STR="Hello\nWorld"
echo $STR
会生成输出
Hello\nWorld
而不是
Hello
World
What should do to have a newline in a string?
注意:这个问题与echo无关。 我知道echo -e
,但我正在寻找一种解决方案,允许将字符串(包括换行符)作为参数传递给其他命令没有类似的选项将 \n
解释为换行符。
This
STR="Hello\nWorld"
echo $STR
produces as output
Hello\nWorld
instead of
Hello
World
What should I do to have a newline in a string?
Note: This question is not about echo.
I'm aware of echo -e
, but I'm looking for a solution that allows passing a string (which includes a newline) as an argument to other commands that do not have a similar option to interpret \n
's as newlines.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(13)
如果您使用的是 Bash,则可以在特别引用的
Hello\nWorld' echo "$STR" # quotes are required here!$'string'
内使用反斜杠转义符。例如,添加\n
:输出:
如果您使用几乎任何其他 shell,只需在字符串中按原样插入换行符:
Bash 可识别 < 中的许多其他反斜杠转义序列代码>$'' 字符串。以下是 Bash 手册页的摘录:
If you're using Bash, you can use backslash-escapes inside of a specially-quoted
Hello\nWorld' echo "$STR" # quotes are required here!$'string'
. For example, adding\n
:Prints:
If you're using pretty much any other shell, just insert the newline as-is in the string:
Bash recognizes a number of other backslash escape sequences in the
$''
string. Here is an excerpt from the Bash manual page:Echo 已经九十年代了,充满了危险,使用它会导致不少于 4GB 的核心转储。说真的,echo 的问题正是 Unix 标准化进程最终发明了 printf 实用程序并解决所有问题的原因。
因此,要在字符串中获取换行符,有两种方法:
有!没有 SYSV 与 BSD 的回声疯狂,所有内容都打印整齐,并且完全可移植地支持 C 转义序列。大家现在请使用
printf
来满足您的所有输出需求,并且永远不要回头。Echo is so nineties and so fraught with perils that its use should result in core dumps no less than 4GB. Seriously, echo's problems were the reason why the Unix Standardization process finally invented the
printf
utility, doing away with all the problems.So to get a newline in a string, there are two ways:
There! No SYSV vs BSD echo madness, everything gets neatly printed and fully portable support for C escape sequences. Everybody please use
printf
now for all your output needs and never look back.我根据其他答案所做的是
What I did based on the other answers was
我发现
-e
标志优雅且直接如果字符串是另一个命令的输出,我只需使用引号
I find the
-e
flag elegant and straight forwardIf the string is the output of another command, I just use quotes
问题不在于外壳。问题实际上在于 echo 命令本身,以及变量插值周围缺少双引号。您可以尝试使用
echo -e
,但并非所有平台都支持该功能,这也是现在推荐使用printf
以实现可移植性的原因之一。您还可以尝试将换行符直接插入到您的 shell 脚本中(如果您正在编写脚本),因此它看起来像...
或等效的
The problem isn't with the shell. The problem is actually with the
echo
command itself, and the lack of double quotes around the variable interpolation. You can try usingecho -e
but that isn't supported on all platforms, and one of the reasonsprintf
is now recommended for portability.You can also try and insert the newline directly into your shell script (if a script is what you're writing) so it looks like...
or equivalently
唯一简单的替代方法是在变量中实际键入新行:
是的,这意味着在代码中需要的地方写入 Enter。
有几个与
换行
字符等效的字符。但所有这些都需要某种工具的“解释”(POSIX printf ):
因此,该工具需要构建一个带有换行符的字符串:
在某些 shell 中,序列 $' 是一种特殊的 shell 扩展。
已知可在 ksh93、bash 和 zsh 中工作:
当然,更复杂的解决方案也是可能的:
或者
新\n行'当然,更复杂的解决方案也是可能的:
或者
The only simple alternative is to actually type a new line in the variable:
Yes, that means writing Enter where needed in the code.
There are several equivalents to a
new line
character.But all those require "an interpretation" by some tool (POSIX printf):
And therefore, the tool is required to build a string with a new-line:
In some shells, the sequence $' is a special shell expansion.
Known to work in ksh93, bash and zsh:
Of course, more complex solutions are also possible:
Or
new\nline'Of course, more complex solutions are also possible:
Or
单引号 '...\n...' 之前的 $ 如下所示,但双引号不起作用。
A $ right before single quotation marks '...\n...' as follows, however double quotation marks doesn't work.
免责声明:我首先写了这篇文章,然后偶然发现了这个问题。我认为这个解决方案尚未发布,并看到 tlwhitec 确实发布了类似的答案。我仍然发布这篇文章,因为我希望这是一个有用且彻底的解释。
简短回答:
这似乎是一个相当便携的解决方案,因为它可以在相当多的 shell 上运行(请参阅评论)。
这样你就可以将真正的换行符放入变量中。
此解决方案的好处是您不必在源代码中使用换行符,因此您可以缩进
您可以按照自己想要的方式编写代码,并且该解决方案仍然有效。这使得它变得健壮。它也是便携式的。
更长的答案:
上述解决方案的说明:
换行符通常会由于命令替换而丢失,但为了防止这种情况,我们添加一个“q”并在之后将其删除。 (双引号的原因将在下面进一步解释。)
我们可以证明该变量包含实际的换行符(0x0A):(
注意,需要
'%s'
,否则 printf 将翻译一个文字'\n'
字符串转换为实际的 0x0A 字符,这意味着我们什么也证明不了。)当然,除了这个答案中提出的解决方案,人们也可以使用它(但是...... ):
...但是这种方法不太健壮,并且很容易因意外缩进代码或忘记事后对其进行缩进而损坏,这使得在(缩进的)函数中使用不方便,而早期的解决方案是健壮的。
现在,至于双引号:
像
nl="$(printf '\nq')"
中那样用双引号"
包围命令替换的原因是,您甚至可以在变量赋值前加上前缀local
关键字或内置函数(例如在函数中),它仍然可以在所有 shell 上工作,而否则dash
shell 会遇到麻烦,因为 dash 会出现问题否则会丢失“q”,并且最终会得到一个空的“nl”变量(同样,由于命令替换)。用另一个例子可以更好地说明这个问题:
上述解决方案的实际示例:
Disclaimer: I first wrote this and then stumbled upon this question. I thought this solution wasn't yet posted, and saw that tlwhitec did post a similar answer. Still I'm posting this because I hope it's a useful and thorough explanation.
Short answer:
This seems quite a portable solution, as it works on quite some shells (see comment).
This way you can get a real newline into a variable.
The benefit of this solution is that you don't have to use newlines in your source code, so you can indent
your code any way you want, and the solution still works. This makes it robust. It's also portable.
Longer answer:
Explanation of the above solution:
The newline would normally be lost due to command substitution, but to prevent that, we add a 'q' and remove it afterwards. (The reason for the double quotes is explained further below.)
We can prove that the variable contains an actual newline character (0x0A):
(Note that the
'%s'
was needed, otherwise printf will translate a literal'\n'
string into an actual 0x0A character, meaning we would prove nothing.)Of course, instead of the solution proposed in this answer, one could use this as well (but...):
... but that's less robust and can be easily damaged by accidentally indenting the code, or by forgetting to outdent it afterwards, which makes it inconvenient to use in (indented) functions, whereas the earlier solution is robust.
Now, as for the double quotes:
The reason for the double quotes
"
surrounding the command substitution as innl="$(printf '\nq')"
is that you can then even prefix the variable assignment with thelocal
keyword or builtin (such as in functions), and it will still work on all shells, whereas otherwise thedash
shell would have trouble, in the sense that dash would otherwise lose the 'q' and you'd end up with an empty 'nl' variable (again, due to command substitution).That issue is better illustrated with another example:
Practical example of the above solution:
我不是 bash 专家,但这个对我有用:
我发现这更容易格式化文本。
I'm no bash expert, but this one worked for me:
I found this easier to formatting the texts.
这并不理想,但我已经编写了大量代码并以类似于问题中使用的方法的方式定义了字符串。接受的解决方案要求我重构大量代码,因此我用
"$'\n'"
替换了每个\n
,这对我有用。This isn't ideal, but I had written a lot of code and defined strings in a way similar to the method used in the question. The accepted solution required me to refactor a lot of the code so instead, I replaced every
\n
with"$'\n'"
and this worked for me.那些只需要换行符并且鄙视破坏缩进的多行代码的挑剔者可以这样做:
Bash(以及可能的其他 shell)在命令替换后吞噬所有尾随换行符,因此您需要结束
printf
带有非换行符的字符串,然后将其删除。这也很容易成为一句空话。Those picky ones that need just the newline and despise the multiline code that breaks indentation, could do:
Bash (and likely other shells) gobble all the trailing newlines after command substitution, so you need to end the
printf
string with a non-newline character and delete it afterwards. This can also easily become a oneliner.我对这里的任何选项都不太满意。这对我有用。
I wasn't really happy with any of the options here. This is what worked for me.
在我的系统(Ubuntu 17.10)上,无论是从命令行输入(进入
sh
)还是作为sh
脚本执行时,您的示例都可以按需要工作:我猜是这样回答你的问题:它确实有效。 (我没有试图弄清楚细节,例如
sh
中\n
的换行符替换究竟在什么时候发生)。但是,我注意到,使用
bash
执行相同的脚本时,其行为会有所不同,并且会打印出Hello\nWorld
:我已经设法使用
bash
获取所需的输出,如下所示:注意
$STR
周围的双引号。如果保存并作为 bash 脚本运行,则其行为相同。以下还给出了所需的输出:
On my system (Ubuntu 17.10) your example just works as desired, both when typed from the command line (into
sh
) and when executed as ash
script:I guess this answers your question: it just works. (I have not tried to figure out details such as at what moment exactly the substitution of the newline character for
\n
happens insh
).However, i noticed that this same script would behave differently when executed with
bash
and would print outHello\nWorld
instead:I've managed to get the desired output with
bash
as follows:Note the double quotes around
$STR
. This behaves identically if saved and run as abash
script.The following also gives the desired output: