[bash] here-document에서 ‘예기치 않은 파일 끝’오류가 발생합니다.

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

/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에서 정말 처음이라서 스스로 알아내는 데 어려움을 겪고 있습니다. 누구든지 도움을 줄 수 있습니까?



답변

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

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

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


답변

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

cat -A myfile.sh

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


답변

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

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

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

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


답변

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

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

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


답변

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를 알고있는 경우 선행 공간이 유지되거나 이동하는 정도를 제어 할 수있는 용이성에서 비롯됩니다.


답변

내가 가지고 싶을 때 문서화 문자열을 내 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.


답변

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