如何在sh中的字符串中添加换行符?

Jua*_*rro 303 sh

这个

STR="Hello\nWorld"
echo $STR
Run Code Online (Sandbox Code Playgroud)

产生输出

Hello\nWorld
Run Code Online (Sandbox Code Playgroud)

代替

Hello
World
Run Code Online (Sandbox Code Playgroud)

如何在字符串中添加换行符?

注意:这个问题不是关于回声. 我知道echo -e,但我正在寻找一种解决方案,允许将一个字符串(包括换行符)作为参数传递给其他命令,这些命令没有类似的选项来解释\n为换行符.

amp*_*ine 316

解决方案是使用$'string',例如:

$ STR=$'Hello\nWorld'
$ echo "$STR"
Hello
World
Run Code Online (Sandbox Code Playgroud)

以下是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.
Run Code Online (Sandbox Code Playgroud)

  • 这是有效的bash,但不是POSIX sh. (67认同)
  • + 1 - 只是一个注释:export varDynamic ="$ varAnother1 $ varAnother2"$'\n' (7认同)
  • @ssc你的例子中没有变量.此外,此方法需要单引号.最后,要包含插值变量,您必须将双引号和特殊单引号字符串连接在一起.例如`H ="你好"; W = "世界"; STR = "$ {H}" $ '\ N' "$ {W】"; echo"$ {STR}"`将在不同的行上回显"Hello"和"World" (6认同)
  • 这确实有文字字符串作为工作的任择议定书要求,但只要变量被替换失败:`STR = $"你好\nWorld"`只是打印`你好\nWorld`. (3认同)
  • @ssc单引号,不是双倍的 (3认同)

Jen*_*ens 154

Echo是九十年代,充满了危险,它的使用应该导致核心转储不低于4GB.说真的,echo的问题是Unix标准化过程最终发明printf实用程序的原因,消除了所有问题.

所以要在字符串中获取换行符:

FOO="hello
world"
BAR=$(printf "hello\nworld\n") # Alternative; note: final newline is deleted
printf '<%s>\n' "$FOO"
printf '<%s>\n' "$BAR"
Run Code Online (Sandbox Code Playgroud)

那里!没有SYSV与BSD的回声疯狂,一切都得到了整齐的打印和完全便携式支持C转义序列.大家请printf现在使用,永远不要回头.

  • 仅限于"干净"的缺陷定义.截至2013年,`$'foo'`语法不是有效的POSIX语法.许多shell都会抱怨. (10认同)
  • `BAR = $(printf"hello \nworld \n")`不会为我打印尾随\n (5认同)
  • @ismael不,`$()`由POSIX指定为**在替换结束时删除一个或多个<newline>字符的序列**. (5认同)
  • 感谢您的回答,我认为它提供了非常好的建议.但请注意,我的原始问题并不是关于如何获取回显来打印换行符,而是如何将换行符添加到shell变量中.你也展示了如何使用printf来做到这一点,但我认为[amphetamachine](http://stackoverflow.com/users/237955/amphetamachine)使用`$'string'`的解决方案更加清晰. (3认同)
  • @Jonny不应该; 命令替换的shell规范表示删除了输出末尾的一个或多个换行符.我意识到这是我的例子意外,并编辑它在printf中包含换行符. (3认同)
  • 好吧(在 bash 中),试试 `printf -v var "%s\n\n" "valuea" "valueb"`。好像保留了最后两个`\n`。线索:`echo -n "$var"|xxd`。:) (2认同)
  • 那就是:在末尾添加一个 x,然后将其删除。并将 printf 重新定义为这个新命令。[重新定义](http://wiki.bash-hackers.org/commands/builtin/printf) 和来自 [Greg's Wiki](http://mywiki.wooledge.org/BashPitfalls#content.3D.24.28) 的 x 技巧。 3Cfile.29)Bash Pitfails 的第 41 点。 (2认同)

zve*_*zda 54

我根据其他答案做了什么

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
Run Code Online (Sandbox Code Playgroud)

  • 呃不是一个漂亮的解决方案.但至少它有效. (3认同)

Pac*_*ace 29

问题不在于shell.问题实际上是echo命令本身,以及变量插值周围缺少双引号.您可以尝试使用echo -e但并非在所有平台上都支持,printf现在建议使用其中一个原因来实现可移植性.

您也可以尝试将换行符直接插入到shell脚本中(如果脚本是您正在编写的脚本),那么它看起来像......

#!/bin/sh
echo "Hello
World"
#EOF
Run Code Online (Sandbox Code Playgroud)

或者等价的

#!/bin/sh
string="Hello
World"
echo "$string"  # note double quotes!
Run Code Online (Sandbox Code Playgroud)


小智 21

  1. 唯一简单的替代方法是在变量中实际输入一个新行:

    $ STR='new
    line'
    $ printf '%s' "$STR"
    new
    line
    
    Run Code Online (Sandbox Code Playgroud)

    是的,这意味着Enter在代码中需要编写代码.

  2. new line角色有几个等价物.

    \n           ### A common way to represent a new line character.
    \012         ### Octal value of a new line character.
    \x0A         ### Hexadecimal value of a new line character.
    
    Run Code Online (Sandbox Code Playgroud)

    但所有这些都需要一些工具(POSIX printf)的"解释" :

    echo -e "new\nline"           ### on POSIX echo, `-e` is not required.
    printf 'new\nline'            ### Understood by POSIX printf.
    printf 'new\012line'          ### Valid in POSIX printf.
    printf 'new\x0Aline'       
    printf '%b' 'new\0012line'    ### Valid in POSIX printf.
    
    Run Code Online (Sandbox Code Playgroud)

    因此,该工具需要使用换行符构建一个字符串:

    $ STR="$(printf 'new\nline')"
    $ printf '%s' "$STR"
    new
    line
    
    Run Code Online (Sandbox Code Playgroud)
  3. 在某些shell中,序列$'是一个特殊的shell扩展.已知可以在ksh93,bash和zsh中工作:

    $ STR=$'new\nline'
    
    Run Code Online (Sandbox Code Playgroud)
  4. 当然,更复杂的解决方案也是可能的:

    $ echo '6e65770a6c696e650a' | xxd -p -r
    new
    line
    
    Run Code Online (Sandbox Code Playgroud)

    要么

    $ echo "new line" | sed 's/ \+/\n/g'
    new
    line
    
    Run Code Online (Sandbox Code Playgroud)


Sim*_*nda 19

我发现-e国旗优雅而直截了当

-e#outputs-e

如果字符串是另一个命令的输出,我只使用引号

-e

  • 其他答案中已经提到了这一点。另外,尽管已经存在,但我只是编辑了一个问题,以强调这个问题不是关于echo的事实。 (2认同)

cao*_*aot 6

单引号前面的$如下所示,但是双引号无效。

$ echo $'Hello\nWorld'
Hello
World
$ echo $"Hello\nWorld"
Hello\nWorld
Run Code Online (Sandbox Code Playgroud)