2010-06-09 3 views
195

ЭтоКак я могу создать новую строку в строке в sh?

STR="Hello\nWorld" 
echo $STR 

производит в качестве выходного

Hello\nWorld 

вместо

Hello 
World 

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

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

ответ

214

решение состоит в том, чтобы использовать $'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. 
+42

, действительный удар, но не POSIX ш. – jmanning2k

+5

+ 1-just a note: export varDynamic = "$ varAnother1 $ varAnother2" $ '\ n' –

+0

на POSIX Я бы набрал 'IFS = '^ J'' и использовал это. Известен любой другой вариант? – Ostap

17

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

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

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

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

#!/bin/sh 
string="Hello 
World" 
echo "$string" # note double quotes! 
107

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 echo madness, все становится аккуратно напечатанной и полностью переносимой поддержкой для escape-последовательностей C. Теперь все, пожалуйста, используйте printf и никогда не оглядывайтесь назад.

+2

Спасибо за этот ответ, я думаю, это дает действительно хороший совет. Обратите внимание, однако, что мой первоначальный вопрос был не совсем о том, как получить эхо для печати новых строк, но как получить новую строку в переменной оболочки. Вы показываете, как это сделать, используя printf, но я думаю, что решение из [amphetamachine] (http://stackoverflow.com/users/237955/amphetamachine) с использованием '$ 'string'' еще более чистое. –

+7

Только для недостаточного определения «чистого». Синтаксис '$ 'foo'' недействителен синтаксисом POSIX по состоянию на 2013 год. Многие оболочки будут жаловаться. – Jens

+1

Спасибо за этот ответ. Я настолько ввернута, что слишком часто использую bash специфические вещи в sh файлах. – totowtwo

33

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

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 
+2

Ух, не очень приятное решение. Но, по крайней мере, это работает. – 2015-11-13 10:40:35

6

Я нахожу -e флаг элегантный и прямо вперед

STR="Hello\nWorld" echo -e $STR #outputs Hello World

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

indexes_diff=$(git diff index.yaml) echo "$indexes_diff"

+1

Это уже упоминалось в других ответах. Кроме того, хотя он уже был там, я только что отредактировал вопрос, чтобы подчеркнуть тот факт, что этот вопрос не * о 'echo'. –

+0

Это не ответ на вопрос –

+0

Это полностью отвечает на вопрос, который я искал! Благодаря! – Kieveli

12
  1. Единственный простой альтернативой является на самом деле ввести новую строку в переменной:

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

    Да, это означает, что писать 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. 
    

    Но все те требуют "интерпретации" какой-то инструмент (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. В некоторых раковинах последовательность $' - специальная оболочка exp ansion. Известный работать в ksh93, Баш и Zsh:

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

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

    Или

    $ echo "new line" | sed 's/ \+/\n/g' 
    new 
    line 
    
+0

Это очень четкий и подробный ответ! –

2

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

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

$STR2 
EOF 
) 
echo "$NEWSTR" 

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

+0

Хорошо старый [heredoc] (https://en.wikipedia.org/wiki/Here_document#Unix_shells). И это, вероятно, совместимо с POSIX! – pyb

2

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

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

Идеально. :) Работает с $ read тоже. – datico

0

В моей системе (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 

Я предполагаю, что это отвечает на ваш вопрос: он просто работает.(Я не пытался разобраться в деталях, например, в какой момент точно замена символа новой строки для \n происходит в sh).

Однако я заметил, что это тот же сценарий будет вести себя по-разному при выполнении с bash и печатал бы Hello\nWorld вместо:

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

Я удалось получить желаемый результат с bash следующим образом:

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

Обратите внимание на двойные кавычки около $STR. Это ведет себя одинаково, если сохраняется и выполняется как сценарий bash.

Следующая также дает желаемый результат:

[bash]§ echo "Hello 
> World" 
Смежные вопросы