sh에서 문자열에 줄 바꿈을 어떻게 넣을 수 있습니까?


339

STR="Hello\nWorld"
echo $STR

출력으로 생성

Hello\nWorld

대신에

Hello
World

문자열에 줄 바꿈을하려면 어떻게해야합니까?

참고 : 이 질문은 echo에 관한 것이 아닙니다 . 나는 알고 echo -e있지만, 줄 바꿈 을 해석하는 비슷한 옵션이없는 다른 명령에 대한 인수로 문자열 (줄 바꿈 포함)을 전달할 수있는 솔루션을 찾고 있습니다 \n.

답변:


353

해결책은 $'string'다음과 같습니다.

$ STR=$'Hello\nWorld'
$ echo "$STR" # quotes are required here!
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.

74
유효한 bash이지만 POSIX sh는 아닙니다.
jmanning2k

7
+ 1 단지 참고 사항 : 수출 varDynamic = "$ varAnother1 $ varAnother2"$ '\ n'을
Yordan 게오르기

3
이것은 실제로 OP가 요청한 그대로 리터럴 문자열과 함께 작동하지만 변수를 대체하자마자 실패 STR=$"Hello\nWorld"합니다 Hello\nWorld. 단순히 인쇄합니다 .
ssc

3
@ssc 작은 따옴표, 두 배가 아닌
miken32

7
@ssc 예제에 변수가 없습니다. 또한이 방법에는 작은 따옴표가 필요합니다. 마지막으로 보간 된 변수를 포함 시키려면 큰 따옴표와 특수한 따옴표로 묶은 문자열을 함께 연결해야합니다. 예를 들면 H="Hello"; W="World"; STR="${H}"$'\n'"${W}"; echo "${STR}"별도의 라인에 "안녕하세요"와 "세계"메아리
JDS

166

Echo는 90 년대에 너무나 위험해서 그 사용으로 인해 코어 덤프가 4GB 이상이어야합니다. 에코의 문제는 유닉스 표준화 프로세스가 마침내 printf유틸리티를 발명하여 모든 문제를 없애는 이유 였습니다.

따라서 문자열에 줄 바꿈을 얻으려면 :

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

그곳에! SYSV vs BSD 에코 광기 없음, 모든 것이 깔끔하게 인쇄되고 C 이스케이프 시퀀스를 완벽하게 지원합니다. 모두들 printf지금 사용 하고 뒤돌아 보지 마십시오.


3
이 답변에 감사드립니다. 정말 좋은 조언을 제공한다고 생각합니다. 그러나 원래의 질문은 실제로 줄 바꿈을 인쇄하기 위해 에코를 얻는 방법이 아니라 쉘 변수로 줄 바꿈을 얻는 방법에 관한 것이 었습니다. 당신은뿐만 아니라 그 사용의 printf를 수행하는 방법을 보여줍니다,하지만 난에서 해결책이라고 생각 amphetamachine 사용은 $'string'심지어 청소기입니다.
Juan A. Navarro

11
'깨끗한'에 대한 부족한 정의에 대해서만. $'foo'구문은 불평 2013 년 많은 조개의 유효 POSIX 구문이 아닙니다.
Jens

5
BAR=$(printf "hello\nworld\n")후미 \ n를 인쇄하지 않습니다
Jonny

3
@ 조니 그것은해서는 안됩니다; 명령 대체에 대한 쉘 스펙은 출력 끝에 하나 이상의 개행이 삭제됨을 나타냅니다. 나는 이것이 내 예에서 예기치 않은 것을 알고 printf에 개행을 포함하도록 편집했습니다.
Jens

5
@ismael No $()는 POSIX 에서 대체가 끝날 때 하나 이상의 <newline> 문자 시퀀스제거하여 지정합니다 .
Jens

61

다른 답변을 기반으로 한 것은

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

30

쉘에 문제가 없습니다. 실제로 문제는 echo명령 자체에 있고 변수 보간에 큰 따옴표가 없습니다. 사용할 수는 echo -e있지만 모든 플랫폼에서 지원되는 것은 아니며 printf이제 이식성을 위해 이유 중 하나를 권장합니다.

또한 개행을 쉘 스크립트에 직접 삽입하여 (스크립트가 작성중인 경우) 다음과 같이 표시 할 수 있습니다.

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

또는 동등하게

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

24

-e우아하고 똑바로 깃발을 찾습니다

bash$ STR="Hello\nWorld"

bash$ echo -e $STR
Hello
World

문자열이 다른 명령의 출력이면 따옴표 만 사용합니다.

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

2
이것은 다른 답변에서 이미 언급되었습니다. 이미 거기 있지만 또한, 난 그냥이 질문은 사실을 강조 할 수있는 질문 편집 한 하지 약을 echo.
Juan A. Navarro

이것은 질문에 대한 답변이 아닙니다
Rohit Gupta

이것은 내가 찾던 질문에 완전히 대답합니다! 감사!
Kieveli

1
나를 위해 잘 일했다. 이 에코를 기반으로 파일을 만드는 데 사용했으며 출력에 새 줄을 올바르게 생성했습니다.
Mateus Leon

echo -e이식성 문제로 유명합니다. 현재 POSIX 이전보다 와일드 웨스트 상황이 적지 만 여전히 선호 할만한 이유는 없습니다 echo -e. 또한 참조 stackoverflow.com/questions/11530203/...
tripleee

21
  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. 일부 쉘에서 시퀀스 $'는 특수 쉘 확장입니다. ksh93, bash 및 zsh에서 작동하는 것으로 알려져 있습니다.

    $ STR=$'new\nline'
  4. 물론보다 복잡한 솔루션도 가능합니다.

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

    또는

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

6

작은 따옴표 '... \ n ...'바로 앞에있는 $는 다음과 같이 사용되지만 큰 따옴표는 작동하지 않습니다.

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

4

나는 bash 전문가는 아니지만이 것이 나를 위해 일했다.

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

$STR2
EOF
)
echo "$NEWSTR"

텍스트 형식을 쉽게 지정할 수 있습니다.


2
좋은 오래된 heredoc . 그리고 아마도 POSIX를 준수 할 것입니다!
pyb

주위에 따옴표 $NEWSTRecho "$NEWSTR"여기에 중요하다
샤디

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

나는 이것이 당신의 질문에 대답한다고 생각합니다 : 그것은 효과가 있습니다. (I는 어떤 순간이 개행 문자 정확히 대체에로 세부 사항을 알아낼 시도하지 않은 \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"

0

개행이 필요하고 들여 쓰기를 깰 여러 줄 코드를 경멸하는 까다로운 것들 :

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

Bash (및 다른 쉘)는 명령 대체 후 모든 후행 줄 바꿈을 수행하므로 printf줄 바꿈 문자가 아닌 문자열 을 종료하고 나중에 삭제해야합니다. 이것은 또한 쉽게 하나의 라이너가 될 수 있습니다.

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

나는 이것이 하나의 행동이 아니라 두 가지 행동이라는 것을 알고 있지만, 내 들여 쓰기 및 이식성 OCD는 이제 평화 롭습니다 \r. 따라서 개행 분할은으로 끝나는 dos 출력에서도 작동 \r\n합니다.

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

0

나는 여기서 어떤 옵션에도 만족하지 않았다. 이것이 나를 위해 일한 것입니다.

str=$(printf "%s" "first line")
str=$(printf "$str\n%s" "another line")
str=$(printf "$str\n%s" "and another line")

그것은 매우 지루한 작성 방법입니다 str=$(printf '%s\n' "first line" "another line" "and another line")(쉘은 명령 대체에서 마지막 줄 바꿈을 편리하게 (또는)하지 않습니다). 여기에 여러 답변이 이미 printf다양한 형태로 홍보 되어 있으므로 별도의 답변으로 가치를 더할 수 있을지 모르겠습니다.
tripleee

짧은 문자열을위한 것이지만 일을 깔끔하게 유지하고 각 줄의 길이가 실제로 60 자이면 깔끔한 방법입니다. 그것이 내가 함께 갔던 해결책이라는 것을 감안할 때, 그것은 당신을 위해, 나중에 의심 할 여지없이 돌아올 때 나 자신을 위해 무언가를 추가합니다.
Adam K Dean

1
긴 문자열조차도 선호합니다 printf '%s\n' "first line" \ (줄 바꿈, 들여 쓰기 'second line'등 ) . printf -v str서브 쉘을 생성하지 않고 변수에 할당하는 방법 도 참조하십시오 .
tripleee
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.