여유 공간이있는 여러 줄 문자열 (보존 들여 쓰기)


409

다음과 같이 미리 정의 된 텍스트를 파일에 쓰고 싶습니다.

text="this is line one\n
this is line two\n
this is line three"

echo -e $text > filename

나는 이런 식으로 기대하고있다 :

this is line one
this is line two
this is line three

그러나 이것을 얻었다 :

this is line one
 this is line two
 this is line three

나는 각각 뒤에 공간이 없다고 \n생각하지만 여분의 공간은 어떻게 나옵니까?


2
잘 모르겠지만 .. text="this is line one\nthis is line two\nthis is line three"같은 줄에 입력하면 어떻게 됩니까? (입력하지 않고)
Yohanes Khosiawan 许先汉

4
\n각 줄에서를 제거하면 이미 새 줄로 이동하여 새 줄로 이동합니다
Mark Setchell

당신은 이미. \n그래서 왜 다음 줄을 새로운 줄에 넣었습니까? 간단히text="this is line one\nthis is line two\nthis is line three"
Jayesh Bhoi

1
\n각 줄의 끝에서를 제거하면 출력이 모두 한 줄로 함께 실행됩니다.
Jonathan Hartley

18
Aha : "$text"에코 라인에서 큰 따옴표를 묶는 것이 중요합니다. 그것들이 없으면 개행 (리터럴 및 '\ n'모두)이 작동하지 않습니다. 그들과 함께 그들은 모두합니다.
Jonathan Hartley

답변:


662

Heredoc이이 목적에 더 편리하게 들립니다. ex 또는 cat 과 같은 명령 인터프리터 프로그램에 여러 명령을 보내는 데 사용됩니다.

cat << EndOfMessage
This is line 1.
This is line 2.
Line 3.
EndOfMessage

이후의 문자열 <<은 중지 할 위치를 나타냅니다.

이 줄을 파일로 보내려면 다음을 사용하십시오.

cat > $FILE <<- EOM
Line 1.
Line 2.
EOM

다음 줄을 변수에 저장할 수도 있습니다.

read -r -d '' VAR << EOM
This is line 1.
This is line 2.
Line 3.
EOM

이것은라는 변수에 행을 저장합니다 VAR.

인쇄 할 때 변수 주위의 따옴표를 기억하십시오. 그렇지 않으면 줄 바꿈 문자가 표시되지 않습니다.

echo "$VAR"

또한 들여 쓰기를 사용하여 코드에서 더 두드러지게 만들 수 있습니다. 이번에 는 탭이 나타나지 않도록 -애프터 <<를 추가하십시오 .

read -r -d '' VAR <<- EOM
    This is line 1.
    This is line 2.
    Line 3.
EOM

그러나 코드에서 들여 쓰기를 위해 공백이 아닌 탭을 사용해야합니다.


38
왜 두 번째와 다섯 번째 코드 블록의 첫 번째 줄에 << 대신 <<-가 있습니까? 특별한 일이 있습니까?
lohfu

35
@ sup3rman '-'선행 탭을 무시합니다. 참조 stackoverflow.com/questions/2500436/...을
kervin

7
상태 0으로 읽기 종료를 어떻게 만들 수 있습니까? 줄 끝을 찾을 수없는 것 같습니다 (-d ''이므로) 1로 종료되므로 스크립트에있을 때 도움이되지 않습니다.
Misha Slyusarev

6
@MishaSlyusarev -d '\ 0'을 사용하고 마지막 줄의 끝에 \ 0을 추가하십시오
Lars Schneider

11
-d옵션을 사용하는 read -r -d '' VARIABLE <<- EOM것이 효과가 없었습니다.
dron22

186

문자열을 변수로 가져 오려고하면 쉬운 또 다른 방법은 다음과 같습니다.

USAGE=$(cat <<-END
    This is line one.
    This is line two.
    This is line three.
END
)

탭으로 문자열을 들여 쓰면 (예 : '\ t') 들여 쓰기가 제거됩니다. 공백으로 들여 쓰기하면 들여 쓰기가 그대로 유지됩니다.

참고 : 마지막 닫는 괄호가 다른 줄에 있음을 의미. END텍스트는 그 자체로 한 줄에 표시되어야합니다.


1
그게 중요한가요? )같은 줄 에서 내 Mac에서 작동 합니다. 나는 무엇을 사이에 간다 있기 때문에 생각 $()자신의 우주에서 실행할거야이며, 실제 명령 어쨌든 ')'이 표시되지 않습니다. 그것이 다른 사람들에게도 효과가 있는지 궁금합니다.
deej

다른 쉘이 사물을 다르게 해석 할 수 있습니다. bash 문서 에서는 어떤 식 으로든 말하지 않는 것처럼 보이지만 모든 예제에는 자체 줄이 있습니다.
Andrew Miner

재미있는 것은 USAGE 변수의 값을 설정하려고 할 때 답을 찾았다는 것입니다. 그래서 당신의 대답은 정확히 일치합니다. :)
Bunyk

1
@deej POSIX 사양에서 : here-document… 구분자와 <newline> 만 포함 된 줄이있을 때까지 계속됩니다
Fornost

1
@Fornost 내가 한 말과 모순되지 않습니다
deej

84

echo전달 된 인수 사이에 공백을 추가합니다. $text변수 확장 및 단어 분할이 적용되므로 echo명령은 다음과 같습니다.

echo -e "this" "is" "line" "one\n" "this" "is" "line" "two\n"  ...

"this"앞에 공백이 추가 될 것입니다. 개행 문자를 제거하고 개행 $text을 유지하기 위해 인용 할 수 있습니다 .

text="this is line one
this is line two
this is line three"

echo "$text" > filename

또는 다음 printf보다 더 강력하고 휴대하기 쉬운를 사용할 수 있습니다 echo.

printf "%s\n" "this is line one" "this is line two" "this is line three" > filename

에서 bash중괄호 확장을 지원하는, 당신도 할 수 :

printf "%s\n" "this is line "{one,two,three} > filename

1
"echo"명령을 사용할 때 mod가 추가 공간을 보는 이유를 설명해 주셔서 감사합니다. 이 답변은 bash 스크립트에서 사용할 때도 잘 작동합니다 (대화 형 쉘 세션과 반대). 이것이 실제 답변 인 것처럼 느껴지고 받아 들여 져야합니다.
onelaview

1
이 답변을 수락해야합니다. 다른 모든 답변은 OP의 고통을 해결하기위한 수많은 흥미로운 다른 방법을 제공 했지만 기술적으로 문제는 "추가 공간이 어떻게 나옵니까?"라는 질문이었습니다. -1 미스터리를 만들어 준 Josh에게 감사합니다!
Dmitry Shevkoplyas 2018 년

45

bash 스크립트에서 다음이 작동합니다.

#!/bin/sh

text="this is line one\nthis is line two\nthis is line three"
echo -e $text > filename

대안 적으로 :

text="this is line one
this is line two
this is line three"
echo "$text" > filename

고양이 파일 이름은 다음을 제공합니다.

this is line one
this is line two
this is line three

Shell Scripts 동안 대체 트릭이 작동하는 것 같지만 bash에서는 작동하지 않는 것 같습니다.
Macindows

3
@Macindows에 대한 -e옵션을 잊어 버린 것 같습니다 echo. 다시 시도하십시오.
Chris Maes

41

모든 줄을 올바르게 들여 쓰기를 원했기 때문에 더 많은 솔루션을 찾았습니다.

  1. 당신은 사용할 수 있습니다 echo:

    echo    "this is line one"   \
        "\n""this is line two"   \
        "\n""this is line three" \
        > filename

    줄 끝에 "\n"바로 넣으면 작동하지 않습니다 \.

  2. 또는 printf더 나은 이식성을 위해 사용할 수 있습니다 (와 관련하여 많은 문제가 발생했습니다 echo).

    printf '%s\n' \
        "this is line one"   \
        "this is line two"   \
        "this is line three" \
        > filename
  3. 또 다른 해결책은 다음과 같습니다.

    text=''
    text="${text}this is line one\n"
    text="${text}this is line two\n"
    text="${text}this is line three\n"
    printf "%b" "$text" > filename

    또는

    text=''
    text+="this is line one\n"
    text+="this is line two\n"
    text+="this is line three\n"
    printf "%b" "$text" > filename
  4. 다른 용액을 혼합하여 달성 printf하고 sed.

    if something
    then
        printf '%s' '
        this is line one
        this is line two
        this is line three
        ' | sed '1d;$d;s/^    //g'
    fi

    들여 쓰기 수준을 코드에 하드 코딩 할 때 이와 같은 형식의 코드를 리팩터링하는 것은 쉽지 않습니다.

  5. 도우미 함수와 일부 변수 대체 트릭을 사용할 수 있습니다.

    unset text
    _() { text="${text}${text+
    }${*}"; }
    # That's an empty line which demonstrates the reasoning behind 
    # the usage of "+" instead of ":+" in the variable substitution 
    # above.
    _ ""
    _ "this is line one"
    _ "this is line two"
    _ "this is line three"
    unset -f _
    printf '%s' "$text"

3b는 코드 들여 쓰기와 문자열 들여 쓰기를 독립적으로 유지하려고 할 때 선호되는 솔루션입니다. 적어도 변수 할당에 2를 사용할 수 없으며 3a보다 더 읽기 쉽습니다. 신경 쓰지 않을 때는 인용 된 문자열을 여러 줄에 열어 두십시오.
Pysis

아주 좋은 대답 특히 3B
수밋 Trehan

"줄 끝에 \ 바로 앞에"\ n "을 넣으면 작동하지 않습니다." - 에코를 사용할 때 유용한 입니다.
Noam Manos

6

다음은 여러 줄 문자열을 변수에 할당하는 선호되는 방법입니다 (멋지다고 생각합니다).

read -r -d '' my_variable << \
_______________________________________________________________________________

String1
String2
String3
...
StringN
_______________________________________________________________________________

밑줄의 수는 두 경우 모두 동일합니다 (여기서는 80).


0

때로는 유용 할 수있는 간단한 한 줄 연결 만 언급하면됩니다.

# for bash

v=" guga "$'\n'"   puga "

# Just for an example.
v2="bar "$'\n'"   foo "$'\n'"$v"

# Let's simplify the previous version of $v2.
n=$'\n'
v3="bar ${n}   foo ${n}$v"

echo "$v3" 

당신은 이와 같은 것을 얻을 것입니다

바 
   푸 
 구가 
   푸가 

모든 앞뒤 공백은 다음과 같이 유지됩니다.

echo "$v3" > filename

0

여러 가지 방법이 있습니다. 나에게 들여 쓰기 끈을 sed에 배관하는 것이 잘 작동합니다.

printf_strip_indent() {
   printf "%s" "$1" | sed "s/^\s*//g" 
}

printf_strip_indent "this is line one
this is line two
this is line three" > "file.txt"

이 답변은 Mateusz Piotrowski 의 답변을 기반으로 했지만 조금 정제되었습니다.


-1

다음과 같이 넣으면 작동합니다.

AA='first line
\nsecond line 
\nthird line'
echo $AA
output:
first line
second line
third line
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.