ヒアドキュメントで「予期しないファイルの終わり」エラーが発生する


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他のものと(ENDOFMESSAGEFINISHなど)が、無駄に。私がオンラインで見つけたほとんどすべてがこのように行われています、そして私はbashに本当に慣れていないので、自分でそれを理解するのに苦労しています。誰か助けを提供できますか?


9
されたEOF行はインデント?それは行の先頭にある必要があります。
バーマー2013

それはそうですが、そのステートメント全体がネストされている場合に限ります。それで、それはずっと左になければなりませんか?
thnkwthprtls 2013

2
また、末尾の文字がないことを確認してください(キャリッジリターンを含む!)
glenn jackman 2013

2
あなたとインデントした場合のみ、タブ文字は、使用することができます<<-EOF- gnu.org/software/bash/manual/bashref.html#Here-Documentsを
グレンはジャックマン

回答:


157

EOFトークンは、行の先頭になければなりません、あなたはそれがで行くコードのブロックと一緒にそれをインデントすることはできません。

書く<<-EOF場合はインデントできますがTab、スペースではなく文字でインデントする必要があります。そのため、コードのブロックがあっても、それでも終わらない可能性があります。

また、行のトークンのに空白がないことを確認してくださいEOF


2
上記のコード例では、EOFトークンは行の先頭にあります。
AndrewKoster20年

編集履歴には表示されませんが、この問題を指摘したのは私だけではなかったため、元々インデントされていたに違いありません。
バーマー

不要な空白をすべて削除しても、このエラーが発生します。
AndrewKoster20年

CR文字を確認し、を使用dos2unixして修正します。
バーマー

17

ヒアドキュメントを開始または終了する行には、おそらく印刷不可能な文字または空白文字(キャリッジリターンなど)が含まれています。これは、2番目の「EOF」が最初の「EOF」と一致せず、ヒアドキュメントのように終了しないことを意味します。そうすべき。これは非常に一般的なエラーであり、テキストエディタだけでは検出が困難です。たとえば、cat次のようにして、印刷できない文字を表示できます。

cat -A myfile.sh

cat -Aソリューションからの出力が明らかになると、問題のある文字を削除します。


7

前のスペースを削除してみてくださいEOF:-

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

使用する<tab>代わりに、<spaces><<のidentのためにと使用- EOFは罰金を動作します。

"-"削除し<tabs>、ではない<spaces>が、少なくともこの作品を。


2
最初の提案は役に立ちません(スペースが問題を引き起こすかどうかを確認するためにテストしましたか?)。2つ目は、EOF行がスペースではなくTABでインデントされている場合にのみ役立ちます。
バーマー2013

終了トークンに先頭のスペースがあってはならないと思います
Rahul Tripathi 2013

2

これを行うと、このエラーが発生する可能性があることに注意してください。

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

そのため<< somefileお読みください< somefile。この場合には。


0

これは、ヒアドキュメント使用せずに複数のインデントされた行処理するための柔軟な方法です。

  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重複この質問のを。

次のようなソリューションの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#区切られた行の2番目の部分を取得します。 (区切り文字として「#」を使用し、最初の列を空にするcsvを考えてください)。

cut -c 2-:結果の文字列の2番目から最後までの文字を取得します

また、空の文字列になるため、エラーなしで最初の引数がないかのようにif [ "$1" = "-h" ]評価されることに注意してくださいFalse


-1

BarmarとJoniが言及した他の回答に加えて、を使用するときにEOFの前後に空白行を残さなければならない場合があることに気づきました<<-EOF


1
私は理論的にも実践的にもこれを支持していません。迷信としての反対票。
トリプリー2017年

1
複数行のヒアドキュメントがあり、リダイレクトするcatために親にラップされていました。フォーマットが原因で、ここを閉じる直前にヒアドキュメントマーカーを追加する必要がありました。そうしないと、この不一致が発生します。おそらくありそうもないシナリオではあるが、そこにいる「一部の」人々にとって完全に有効であると賛成する。
SidOfc

私は迷信に貢献するのが嫌いですが、私もこの問題を抱えていて、EOFの終了後に空白行を追加しました。(dockerで実行されているubuntu 19.10。これはbootstrap.shスクリプトにありました)。空白行でこのエラーが修正されました。
NDP
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.