Как получить перевод строки в sh? - PullRequest
278 голосов
/ 09 июня 2010

Этот

STR="Hello\nWorld"
echo $STR

выводит в качестве вывода

Hello\nWorld

вместо

Hello
World

Что мне нужно сделать, чтобы в строке была новая строка?

Примечание: Этот вопрос не о эхо . Мне известно о echo -e, но я ищу решение, которое позволяет передавать строку (которая включает в себясимвол новой строки) в качестве аргумента других команд , которые не имеют аналогичной возможности интерпретировать \n как символы новой строки.

Ответы [ 11 ]

288 голосов
/ 06 июля 2010

Решением является использование $'string', например:

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

Вот выдержка из страницы руководства 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.
148 голосов
/ 16 мая 2012

Echo настолько девяностых и настолько чреват опасностями, что его использование должно привести к дампам ядра не менее 4 ГБ. Серьезно, проблемы с эхо были причиной того, что процесс стандартизации Unix, наконец, изобрел утилиту printf, избавившись от всех проблем.

Итак, чтобы получить новую строку в строке:

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

Там! Нет SYSV против BSD эха безумия, все становится аккуратно напечатано и полностью переносимая поддержка C escape-последовательностей. Всем, пожалуйста, используйте printf сейчас и никогда не оглядывайтесь назад.

48 голосов
/ 01 декабря 2012

То, что я сделал, основываясь на других ответах, было

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
27 голосов
/ 09 июня 2010

Проблема не с оболочкой. Проблема на самом деле в самой команде echo и в отсутствии двойных кавычек вокруг интерполяции переменных. Вы можете попробовать использовать echo -e, но это поддерживается не на всех платформах, и одна из причин, по которой printf теперь рекомендуется для переносимости.

Вы также можете попробовать вставить новую строку непосредственно в скрипт оболочки (если скрипт - это то, что вы пишете), чтобы он выглядел как ...

#!/bin/sh
echo "Hello
World"
#EOF

или эквивалентно

#!/bin/sh
string="Hello
World"
echo "$string"  # note double quotes!
19 голосов
/ 30 марта 2016
  1. Единственная простая альтернатива - фактически ввести новую строку в переменную:

    $ STR='new
    line'
    $ printf '%s' "$STR"
    new
    line
    

    Да, это означает запись Введите , где это необходимо в коде.

  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.
    

    Но все они требуют «интерпретации» каким-либо инструментом ( 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.
    

    И, следовательно, инструмент необходим для созданиястрока с новой строкой:

    $ STR="$(printf 'new\nline')"
    $ printf '%s' "$STR"
    new
    line
    
  3. В некоторых оболочках последовательность $ ' является специальным расширением оболочки.Известно, что работает в ksh93, bash и zsh:

    $ STR=$'new\nline'
    
  4. Конечно, возможны и более сложные решения:

    $ echo '6e65770a6c696e650a' | xxd -p -r
    new
    line
    

    или

    $ echo "new line" | sed 's/ \+/\n/g'
    new
    line
    
11 голосов
/ 05 июня 2015

Я считаю флаг -e элегантным и понятным

bash$ STR="Hello\nWorld"

bash$ echo -e $STR
Hello
World

Если строка является выводом другой команды, я просто использую кавычки

indexes_diff=$(git diff index.yaml)
echo "$indexes_diff"
4 голосов
/ 11 апреля 2017

A $ перед одинарными кавычками '... \ n ...', как показано ниже, однако двойные кавычки не работают.

3 голосов
/ 14 августа 2016

Я не эксперт по Bash, но этот работал для меня:

STR1="Hello"
STR2="World"
NEWSTR=$(cat << EOF
$STR1

$STR2
EOF
)
echo "$NEWSTR"

Мне было проще форматировать тексты.

0 голосов
/ 25 марта 2019

Я был не очень доволен ни одним из вариантов здесь. Это то, что сработало для меня.

str=$(printf "%s" "first line")
str=$(printf "$str\n%s" "another line")
str=$(printf "$str\n%s" "and another line")
0 голосов
/ 28 августа 2018

Те разборчивые, которым нужен только перевод строки и презирающий многострочный код, который нарушает отступ, могут сделать:

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

Bash (и, вероятно, другие оболочки) поглощают все завершающие символы новой строки после подстановки команды, поэтому вам нужно завершить строку printf не символом новой строки и затем удалить ее. Это также может легко стать вкладчиком.

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

Я знаю, что это два действия вместо одного, но мое OCD с отступами и переносимостью теперь в мире :) Я изначально разработал это, чтобы иметь возможность разделять вывод, разделенный только на новую строку, и я использовал модификацию, которая использует \r как завершающий символ. Это делает расщепление новой строки работоспособным даже для вывода dos, заканчивающегося \r\n.

IFS="$(printf '\n\r')"
...