This

STR="Hello\nWorld"
echo $STR

作为输出产生

Hello\nWorld

而不是

Hello
World

我应该做什么有一个换行在字符串?

注意:此问题与echo无关。 我知道echo -e,但我正在寻找一种解决方案,允许传递一个字符串(其中包括换行符)作为参数到其他命令,没有类似的选项来解释\n的换行符。


当前回答

如果你正在使用Bash,你可以在一个特别引用的$'string'中使用反斜杠转义。例如,添加\n:

STR=$'Hello\nWorld'
echo "$STR" # quotes are required here!

打印:

Hello
World

如果你使用的是其他shell,只需在字符串中插入换行符:

STR='Hello
World'

Bash在$ "字符串中识别出许多其他反斜杠转义序列。以下是Bash手册页面的节选:

Words of the form $'string' are treated specially. The word expands to
string, with backslash-escaped characters replaced as specified by the
ANSI C standard. Backslash escape sequences, if present, are decoded
as follows:
      \a     alert (bell)
      \b     backspace
      \e
      \E     an escape character
      \f     form feed
      \n     new line
      \r     carriage return
      \t     horizontal tab
      \v     vertical tab
      \\     backslash
      \'     single quote
      \"     double quote
      \nnn   the eight-bit character whose value is the octal value
             nnn (one to three digits)
      \xHH   the eight-bit character whose value is the hexadecimal
             value HH (one or two hex digits)
      \cx    a control-x character

The expanded result is single-quoted, as if the dollar sign had not
been present.

A double-quoted string preceded by a dollar sign ($"string") will cause
the string to be translated according to the current locale. If the
current locale is C or POSIX, the dollar sign is ignored. If the
string is translated and replaced, the replacement is double-quoted.

其他回答

在单引号'…\n…,但是双引号不能用。

$ echo $'Hello\nWorld'
Hello
World
$ echo $"Hello\nWorld"
Hello\nWorld

我根据其他答案所做的是

NEWLINE=$'\n'
my_var="__between eggs and bacon__"
echo "spam${NEWLINE}eggs${my_var}bacon${NEWLINE}knight"

# which outputs:
spam
eggs__between eggs and bacon__bacon
knight

Echo是90年代的,而且充满了危险,使用它应该会导致内核转储不少于4GB。严肃地说,echo的问题是Unix标准化进程最终发明printf实用程序的原因,它解决了所有问题。

要在字符串中获取换行符,有两种方法:

# 1) Literal newline in an assignment.
FOO="hello
world"
# 2) Command substitution.
BAR=$(printf "hello\nworld\n") # Alternative; note: final newline is deleted
printf '<%s>\n' "$FOO"
printf '<%s>\n' "$BAR"

在那里!没有SYSV和BSD的回声疯狂,所有东西都被整齐地打印出来,并完全支持C转义序列。请大家现在就使用printf来满足所有的输出需求,不要回头。

那些只需要换行符而不喜欢破坏缩进的多行代码的挑剔的人可以这样做:

IFS="$(printf '\nx')"
IFS="${IFS%x}"

Bash(可能还有其他shell)在命令替换之后会占用所有尾随的换行符,因此需要用非换行符结束printf字符串,然后删除它。这也可以很容易地成为一个联机程序。

IFS="$(printf '\nx')" IFS="${IFS%x}"

我知道这是两个动作而不是一个,但我的缩进和可移植性强迫症现在是和平的:)我最初开发这个是为了能够分割换行分离的输出,我最终使用了一个修改,使用\r作为结束字符。这使得换行分割甚至适用于以\r\n结尾的dos输出。 IFS = " $ (printf ' r \ n \ ')”

在我的系统(Ubuntu 17.10)上,你的例子就像预期的那样工作,无论是从命令行输入(到sh)还是作为sh脚本执行:

[bash]§ sh
$ STR="Hello\nWorld"
$ echo $STR
Hello
World
$ exit
[bash]§ echo "STR=\"Hello\nWorld\"
> echo \$STR" > test-str.sh
[bash]§ cat test-str.sh 
STR="Hello\nWorld"
echo $STR
[bash]§ sh test-str.sh 
Hello
World

我想这回答了你的问题:它就是有效。(我没有试图弄清楚诸如在sh中换行符替换\n的具体时间)。

然而,我注意到这个脚本在使用bash执行时会表现不同,而是会打印出Hello\nWorld:

[bash]§ bash test-str.sh
Hello\nWorld

我已经设法获得所需的输出与bash如下:

[bash]§ STR="Hello
> World"
[bash]§ echo "$STR"

注意$STR周围的双引号。如果保存并作为bash脚本运行,则行为相同。

下面也给出了期望的输出:

[bash]§ echo "Hello
> World"