Bash 스크립트에서 heredoc을 파일에 어떻게 쓸 수 있습니까?


답변:


1072

고급 Bash 스크립팅 안내서 19 장 . 여기 문서를 읽으십시오 .

다음은 파일에 내용을 쓰는 예제입니다. /tmp/yourfilehere

cat << EOF > /tmp/yourfilehere
These contents will be written to the file.
        This line is indented.
EOF

마지막 'EOF'(The LimitString)는 단어 앞에 공백이 없어야합니다. 왜냐하면 단어 LimitString가 인식되지 않기 때문 입니다.

쉘 스크립트에서는 들여 쓰기를 사용하여 코드를 읽을 수 있지만 여기 문서 내의 텍스트를 들여 쓰는 것이 바람직하지 않을 수 있습니다. 이 경우 <<-(대쉬 다음에)를 사용하여 선행 탭을 비활성화 하십시오 ( 이를 테스트하려면 실제 탭 문자를 여기에서 인쇄 할 수 없으므로 선행 공백을 탭 문자바꿔야합니다 .)

#!/usr/bin/env bash

if true ; then
    cat <<- EOF > /tmp/yourfilehere
    The leading tab is ignored.
    EOF
fi

텍스트의 변수를 해석하지 않으려면 작은 따옴표를 사용하십시오.

cat << 'EOF' > /tmp/yourfilehere
The variable $FOO will not be interpreted.
EOF

heredoc을 명령 파이프 라인을 통해 파이프하려면 :

cat <<'EOF' |  sed 's/a/b/'
foo
bar
baz
EOF

산출:

foo
bbr
bbz

... 또는 heredoc을 다음을 사용하여 파일에 작성하십시오 sudo.

cat <<'EOF' |  sed 's/a/b/' | sudo tee /etc/config_file.conf
foo
bar
baz
EOF

11
Bash가 필요하지 않습니다.이 기능은 Bourne / Korn / POSIX 쉘에도 있습니다.
야누스 트롤 슨

5
무엇에 대해 <<<, 그들은 무엇을 불렀습니까?
Jürgen Paul

18
@PineappleUndertheSea <<<를 'Here Strings'라고합니다. 다음과 같은 코드 tr a-z A-Z <<< 'one two three'는 문자열이 ONE TWO THREE됩니다. 자세한 내용은 en.wikipedia.org/wiki/Here_document#Here_strings
Stefan Lasiewski에서 18시 03 분

8
마지막 EOF는 공백이 없어야 중 하나를. 적어도 bash에서, 이것은 구분자로 인식되지 않습니다.
carpii

10
특정 히어 닥 오히려 함유 치환보다는 문자 만족하도록 구성되어 있기 때문에, 있어야 <<'EOF'보다는 <<EOF.
Charles Duffy

152

대신 사용 cat및 I / O를 재 지정이 사용하기 유용 할 수 있습니다 tee대신 :

tee newfile <<EOF
line 1
line 2
line 3
EOF

보다 간결하고 리디렉션 연산자와 달리 sudo루트 권한이있는 파일에 쓰기가 필요한 경우 이를 결합 할 수 있습니다 .


18
> /dev/nullhere 파일의 내용이 생성 될 때 stdout에 표시되지 않도록 첫 번째 줄 끝에 추가하는 것이 좋습니다 .
Joe Carroll

11
사실, 그러나 귀하의 솔루션은 sudo간결함이 아니라 와의 호환성으로 인해 호소했습니다. :-)
Joe Carroll

2
이 방법을 사용하여 기존 파일에 어떻게 추가 하시겠습니까?
MountainX

5
@MountainX 체크 아웃 man tee. -a덮어 쓰기 대신 추가 하려면 플래그를 사용하십시오 .
Livven

3
때때로 감독해야 할 구성 스크립트에서 사용 하려면 내용을 인쇄 하기 때문에 이것을 좋아합니다 .
Alois Mahdal

59

노트 :

질문 ( bash 문서 의 파일에 here 문서 (여기서는 heredoc ) 을 쓰는 방법 은 무엇입니까?)에는 적어도 3 가지 주요 독립 차원 또는 하위 질문이 있습니다.

  1. 기존 파일을 덮어 쓰거나 기존 파일에 추가하거나 새 파일에 쓰시겠습니까?
  2. 사용자 또는 다른 사용자 (예 root:)가 파일을 소유하고 있습니까?
  3. heredoc의 내용을 문자 그대로 쓰거나 bash가 heredoc 내부의 변수 참조를 해석하도록 하시겠습니까?

(중요하지 않은 다른 측정 기준 / 문의가 있습니다. 추가하려면이 답변을 수정하십시오.) 여기에 나열된 질문의 측정 기준과 다양한 구분 식별자가있는 더 중요한 조합이 있습니다. 에 대해 신성한 EOF, 구분 식별자로 사용하는 문자열이 heredoc 내에서 발생 하지 않도록 하십시오.

  1. heredoc 내에서 변수 참조를 대체하여 기존 파일을 덮어 쓰거나 새 파일에 쓰려면

    cat << EOF > /path/to/your/file
    This line will write to the file.
    ${THIS} will also write to the file, with the variable contents substituted.
    EOF
  2. heredoc 내에서 변수 참조를 대체하여 기존 파일을 추가하거나 새 파일에 쓰려면

    cat << FOE >> /path/to/your/file
    This line will write to the file.
    ${THIS} will also write to the file, with the variable contents substituted.
    FOE
  3. heredoc의 리터럴 내용으로 기존 파일을 덮어 쓰거나 새 파일에 쓰려면

    cat << 'END_OF_FILE' > /path/to/your/file
    This line will write to the file.
    ${THIS} will also write to the file, without the variable contents substituted.
    END_OF_FILE
  4. heredoc의 리터럴 내용으로 기존 파일을 추가하거나 새 파일에 쓰려면

    cat << 'eof' >> /path/to/your/file
    This line will write to the file.
    ${THIS} will also write to the file, without the variable contents substituted.
    eof
  5. heredoc 내에서 변수 참조를 대체하여 루트가 소유 한 기존 파일을 덮어 쓰거나 새 파일에 쓰려면

    cat << until_it_ends | sudo tee /path/to/your/file
    This line will write to the file.
    ${THIS} will also write to the file, with the variable contents substituted.
    until_it_ends
  6. heredoc의 리터럴 내용으로 user = foo가 소유 한 기존 파일을 추가하거나 새 파일에 쓰려면 다음을 수행하십시오.

    cat << 'Screw_you_Foo' | sudo -u foo tee -a /path/to/your/file
    This line will write to the file.
    ${THIS} will also write to the file, without the variable contents substituted.
    Screw_you_Foo

# 6이 최고입니다. 그러나 기존 파일의 내용을 # 6으로 어떻게 덮어 쓰나요?
Aleksandr Makov

2
@ Aleksandr Makov : 기존 파일의 내용을 # 6으로 어떻게 덮어 씁니까? -a== --append; 생략 즉, tee -a-> tee. 참조 info tee(난 여기가 인용 싶지만, 주석 마크 업이 너무 제한됩니다.
TomRoche

1
# 6 대신에 고양이와 배관을 티로 사용하면 이점이 sudo tee /path/to/your/file << 'Screw_you_Foo'있습니까?
codemonkee

추가 예제 FOE대신에 왜 EOF?
becko

2
@becko : 레이블이 레이블이라는 것을 설명하기 위해. 각 예제에서 다른 레이블을 사용했습니다.
TomRoche

41

@Livven의 답변을 바탕으로 유용한 조합이 있습니다.

  1. 변수 대체, 선행 탭 유지, 파일 덮어 쓰기, 표준 출력으로 에코

    tee /path/to/file <<EOF
    ${variable}
    EOF
  2. 변수 대체 없음 , 선행 탭 유지, 파일 덮어 쓰기, 표준 출력으로 에코

    tee /path/to/file <<'EOF'
    ${variable}
    EOF
  3. 변수 대체, 선행 탭 제거 , 파일 덮어 쓰기, 표준 출력으로 에코

    tee /path/to/file <<-EOF
        ${variable}
    EOF
  4. 변수 치환, 선행 탭 유지, 파일에 추가 , 표준 출력에 에코

    tee -a /path/to/file <<EOF
    ${variable}
    EOF
  5. 변수 대체, 선행 탭 유지, 파일 덮어 쓰기, 표준 에코에 에코 없음

    tee /path/to/file <<EOF >/dev/null
    ${variable}
    EOF
  6. 상기가 결합 될 수 sudo뿐만

    sudo -u USER tee /path/to/file <<EOF
    ${variable}
    EOF

16

루트 권한이 필요한 경우

대상 파일에 루트 권한이 필요한 경우 |sudo tee대신 다음을 사용하십시오 >.

cat << 'EOF' |sudo tee /tmp/yourprotectedfilehere
The variable $FOO will *not* be interpreted.
EOF

여기 문서에 변수를 전달할 수 있습니까? 어떻게 $ FOO를 해석 할 수 있었습니까?
user1527227

@ user1527227 여기 예제 파일에 나와있는 것처럼 : $ FOO 변수는 해석 되지 않습니다 .
Sroo Stroobandt

아래에서 나는이 답변을 Stefan Lasiewski 의 답변과 결합하고 구성하려고 시도했습니다 .
TomRoche

3
@ user1527227 EOF를 작은 따옴표로 묶지 마십시오. 그러면 $ FOO가 해석됩니다.
imnd_neel

11

이 문제가있을 수있는 미래의 사람들을 위해 다음 형식이 작동했습니다.

(cat <<- _EOF_
        LogFile /var/log/clamd.log
        LogTime yes
        DatabaseDirectory /var/lib/clamav
        LocalSocket /tmp/clamd.socket
        TCPAddr 127.0.0.1
        SelfCheck 1020
        ScanPDF yes
        _EOF_
) > /etc/clamd.conf

6
괄호가 필요하지 않습니다. cat << END > afile그 뒤에 heredoc이 완벽하게 작동합니다.
glenn jackman 2018 년

고마워, 이것은 실제로 내가 겪었던 또 다른 문제를 해결했습니다. 여기 몇 가지 문서 후에 몇 가지 문제가있었습니다. 나는 그것이 위의 조언이 그것을 고치 듯이, 파렌과 관련이 있다고 생각합니다.
Joshua Enfield

2
작동하지 않습니다. 출력 리디렉션 cat은 허용 된 답변에 표시된대로 시작하는 줄의 끝에 있어야합니다 .
추후 공지가있을 때까지 일시 중지되었습니다.

2
@DennisWilliamson 그것은 효과가 있습니다. 전체 cat는 서브 쉘 내부에서 실행되며 서브 쉘의 모든 출력은 파일로 리디렉션됩니다
Izkata

2
@ Izkata :이 답변의 편집 기록을 보면 괄호가 주석을 제거하기 전에 제거 된 다음 나중에 다시 추가되었습니다. glenn jackman (및 나의) 의견이 적용됩니다.
추후 공지가있을 때까지 일시 중지되었습니다.

3

인스턴스로 사용할 수 있습니다.

먼저 (ssh 연결 만들기) :

while read pass port user ip files directs; do
    sshpass -p$pass scp -o 'StrictHostKeyChecking no' -P $port $files $user@$ip:$directs
done <<____HERE
    PASS    PORT    USER    IP    FILES    DIRECTS
      .      .       .       .      .         .
      .      .       .       .      .         .
      .      .       .       .      .         .
    PASS    PORT    USER    IP    FILES    DIRECTS
____HERE

둘째 (실행 명령) :

while read pass port user ip; do
    sshpass -p$pass ssh -p $port $user@$ip <<ENDSSH1
    COMMAND 1
    .
    .
    .
    COMMAND n
ENDSSH1
done <<____HERE
    PASS    PORT    USER    IP
      .      .       .       .
      .      .       .       .
      .      .       .       .
    PASS    PORT    USER    IP    
____HERE

셋째 (실행 명령) :

Script=$'
#Your commands
'

while read pass port user ip; do
    sshpass -p$pass ssh -o 'StrictHostKeyChecking no' -p $port $user@$ip "$Script"

done <<___HERE
PASS    PORT    USER    IP
  .      .       .       .
  .      .       .       .
  .      .       .       .
PASS    PORT    USER    IP  
___HERE

넷째 (변수 사용) :

while read pass port user ip fileoutput; do
    sshpass -p$pass ssh -o 'StrictHostKeyChecking no' -p $port $user@$ip fileinput=$fileinput 'bash -s'<<ENDSSH1
    #Your command > $fileinput
    #Your command > $fileinput
ENDSSH1
done <<____HERE
    PASS    PORT    USER    IP      FILE-OUTPUT
      .      .       .       .          .
      .      .       .       .          .
      .      .       .       .          .
    PASS    PORT    USER    IP      FILE-OUTPUT
____HERE

-1

나는 들여 쓰기 스크립트에서 결정, 가독성 및 표현을 위해이 방법을 좋아합니다.

<<-End_of_file >file
       foo bar
End_of_file

캐릭터 →       는 어디에 있습니까 tab?

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.