here-document에서 '예기치 않은 파일 끝'오류가 발생합니다.


82

터미널에서 이메일을 보내려면 스크립트가 필요합니다. 여기와 다른 온라인 사이트에서 본 내용을 기반으로 다음과 같이 형식을 지정했습니다.

/var/mail -s "$SUBJECT" "$EMAIL" << EOF
Here's a line of my message!
And here's another line!
Last line of the message here!
EOF

그러나 이것을 실행하면 다음 경고가 표시됩니다.

myfile.sh: line x: warning: here-document at line y delimited by end-of-file (wanted 'EOF')

myfile.sh: line x+1: syntax error: unexpected end of file

... 여기서 줄 x는 프로그램에서 마지막으로 작성된 코드 줄이고 줄 y는 그 /var/mail안에 있는 줄입니다 . 나는 대체 해봤 EOF다른 것들과 ( ENDOFMESSAGE, FINISH, 등)하지만 아무 소용. 내가 온라인에서 찾은 거의 모든 것이 이런 식으로 이루어졌고 나는 bash에서 정말 처음이라서 스스로 알아내는 데 어려움을 겪고 있습니다. 누구든지 도움을 줄 수 있습니까?


9
는 IS EOF라인 들여 쓰기? 줄의 시작 부분에 있어야합니다.
Barmar 2015 년

그러나 전체 문이 중첩되는 한만 해당됩니다. 그래서 왼쪽 끝까지 있어야하나요?
thnkwthprtls 2013 년

2
또한, 후행 문자 없도록 (캐리지 리턴을 포함하여!)
글렌 잭맨

2
탭 문자 들여 쓰면 다음을 사용할 수 있습니다. <<-EOF- gnu.org
glenn jackman

답변:


156

EOF토큰은 행의 시작 부분에 있어야합니다, 당신은 함께가는 코드 블록과 함께 그것을 들여 수 없습니다.

쓰면 <<-EOF들여 쓰기를 할 수 있지만 Tab공백이 아닌 문자 로 들여 쓰기를해야 합니다. 따라서 코드 블록으로도 끝나지 않을 수도 있습니다.

또한 라인 의 토큰 뒤에 공백이 없는지 확인하십시오 EOF.


2
위의 코드 예제에서 EOF 토큰은 줄의 시작 부분에 있습니다.
Andrew Koster

이 문제를 지적한 사람은 나 뿐만이 아니었기 때문에 편집 기록에서는 볼 수 없지만 원래 들여 쓰기 된 것 같습니다.
Barmar

불필요한 공백을 모두 제거해도이 오류가 발생합니다.
Andrew Koster

CR 문자를 확인하고 사용 dos2unix하여 수정하십시오.
Barmar

17

here-doc를 시작하거나 끝나는 줄에는 인쇄 할 수 없거나 공백 문자 (예 : 캐리지 리턴)가있을 수 있습니다. 이는 두 번째 "EOF"가 첫 번째 "EOF"와 일치하지 않고 here-doc를 끝내지 않음을 의미합니다. 그래야합니다. 이것은 매우 일반적인 오류이며 텍스트 편집기만으로는 감지하기 어렵습니다. 예를 들어 다음과 cat같이 인쇄 할 수없는 문자를 표시 할 수 있습니다 .

cat -A myfile.sh

cat -A솔루션 의 출력을 확인 하면 문제가되는 문자를 제거하십시오.


7

다음 전에 선행 공백을 제거하십시오 EOF.

/var/mail -s "$SUBJECT" "$EMAIL" <<-EOF

ident <tab>대신 <spaces>사용하고 <<-EOF를 사용하면 잘 작동합니다.

"-"제거 <tabs>하지 <spaces>만, 적어도이 작품을.


2
첫 번째 제안은 도움이되지 않습니다 (공간이 문제를 일으키는 지 테스트 했습니까?). 두 번째는 EOF 줄이 공백이 아닌 TAB으로 들여 쓰기 된 경우에만 도움이됩니다.
Barmar 2015 년

종료 토큰에는 선행 공백이 없어야한다고 생각합니다
Rahul Tripathi

2

이렇게하면이 오류가 발생할 수도 있습니다.

while read line; do
  echo $line
done << somefile

이 경우 << somefile읽어야 하기 때문 < somefile입니다.


0

heredoc 사용 하지 않고 들여 쓰기 된 여러 줄 처리 할 수있는 유연한 방법이 있습니다.

  echo 'Hello!'
  sed -e 's:^\s*::' < <(echo '
    Some indented text here.
    Some indented text here.
  ')
  if [[ true ]]; then
    sed -e 's:^\s\{4,4\}::' < <(echo '
      Some indented text here.
        Some extra indented text here.
      Some indented text here.
    ')
  fi

이 솔루션에 대한 몇 가지 참고 사항 :

  • 내용에 간단한 따옴표가있을 것으로 예상되는 경우에는이를 사용하여 이스케이프 \하거나 문자열 구분 기호를 큰 따옴표로 바꾸십시오. 후자의 경우 유사한 구성 $(command)이 해석 될 수 있도록주의하십시오 . 문자열에 간단한 따옴표와 큰 따옴표가 모두 포함되어 있으면 적어도 종류를 이스케이프해야합니다.
  • 주어진 예는 후행 빈 줄을 인쇄합니다.이 줄을 제거하는 방법은 여러 가지가 있습니다. 여기에는 제안을 깔끔하게 유지하기 위해 포함되지 않았습니다.
  • 유연성은 물론 몇 가지 sed REGEXP를 알고있는 경우 선행 공간이 유지되거나 이동하는 정도를 제어 할 수있는 용이성에서 비롯됩니다.

0

내가 가지고 싶을 때 문서화 문자열을 내 bash는 기능, 나는의 제안과 유사한 솔루션을 사용 user12205 A의 중복 이 질문을.

다음과 같은 솔루션에 대해 USAGE를 정의하는 방법을 참조하십시오.

  • 선택한 IDE에서 나를 위해 자동 포맷 (숭고함)
  • 여러 줄
  • 들여 쓰기로 공백이나 탭을 사용할 수 있습니다.
  • 주석 내의 들여 쓰기를 유지합니다.
function foo {
    # Docstring
    read -r -d '' USAGE <<'    END'
        # This method prints foo to the terminal.
        #
        # Enter `foo -h` to see the docstring.
        #      It has indentations and multiple lines.
        #
        # Change the delimiter if you need hashtag for some reason.
        # This can include $$ and = and eval, but won't be evaluated
    END


    if [ "$1" = "-h" ]
    then
        echo "$USAGE" | cut -d "#" -f 2 | cut -c 2-
        return
    fi

    echo "foo"
}

따라서 결과 foo -h:

This method prints foo to the terminal.

Enter `foo -h` to see the docstring.
     It has indentations and multiple lines.

Change the delimiter if you need hashtag for some reason.
This can include $$ and = and eval, but won't be evaluated

설명

cut -d "#" -f 2: #구분 된 줄 의 두 번째 부분을 검색합니다 . (구분 기호로 "#"을 사용하고 첫 번째 열이 비어있는 csv를 생각해보십시오.)

cut -c 2-: 결과 문자열의 두 번째에서 끝 문자 검색

또한 빈 문자열이되기 때문에 오류없이 첫 번째 인수가없는 if [ "$1" = "-h" ]것처럼 평가됩니다 False.


-1

Barmar와 Joni가 언급 한 다른 답변과 함께 <<-EOF.


1
나는 이론이나 실습에서 이것에 대한지지를 찾지 못합니다. 미신으로 찬성.
tripleee 2011

1
여기에 여러 줄로 된 here-doc를 괄호로 묶어 리디렉션 cat하고 서식으로 인해 여기에서 문서를 닫기 직전에 닫는 괄호 앞에 엔터를 추가해야했습니다. 그렇지 않으면이 불일치가 발생합니다. 아마도 가능성이 희박한 시나리오 일지라도 "일부"사람들에게 완전히 유효한 것으로 업 보팅.
SidOfc

미신에 기여하는 것이 싫지만이 문제도 겪고 있었고 EOF가 끝난 후 빈 줄을 추가했습니다. (도커에서 실행중인 우분투 19.10, 이것은 bootstrap.sh 스크립트에있었습니다). 빈 줄이이 오류를 수정했습니다.
NDP
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.