現在700行以上あるbashスクリプトがあります。特に長い編集を行った後、次のようなエラーが発生します。
./run_me.sh: line 693: unexpected EOF while looking for matching `''
./run_me.sh: line 702: syntax error: unexpected end of file
ただし、693行目で確認できる問題はありません。引用もありません。
私はbash -x run_me.sh
を実行してみましたが、最後の行の実行を確認できますが、その行にも問題はありません(その行と693の間のコードは、事実上、ほとんどのコードです)。
コード全体をコメントアウトすることはできますが、EOFエラーが発生するエラーではなく、関数の欠落などによるエラーが発生する可能性が高くなります。
では、行番号が誤って報告された場合、欠落している引用を見つけるにはどうすればよいですか?
(とにかく、なぜbashの行番号の報告がこれまでのところ遠いのですか?)
ちなみに、特定のエラーを(スワスをコメント化して)見つけました。これは、エラーメッセージで示された行の近くの任意の行番号の変数展開で実際に}
が欠落していたものです。ここで助けて、例えば"${MY_ARRAY[@]"
("${MY_ARRAY[@]}"
である必要があります)にブレースがありません。
ローテクなアプローチは
tr -cd "'\n" < run_me.sh | awk 'length%2==1 {print NR, $0}'
tr
は、単一引用符と改行を除くすべての文字を削除します。awk
は、奇数の文字(つまり、一致しない引用符)を持つ行を識別します。個別に確認してください。 "That's not a bug!"
のような有効な文字列にはフラグが付けられることに注意してください。これで問題が明らかにならない場合は、'"\n'
を使用して再試行してください(一致しない二重引用符を見つけます)。次に、tr
を展開して、()
、{}
、最終的には{}
を通過できるようにします。この時点で、出力を手動で検査することはあまり実りのない追求になります。 (
と)
は通常、同じ行内で一致し、引用符と角括弧はほとんど常に一致しますが、これは{
と}
には当てはまりません。
問題を中括弧の不一致に絞り込んだ場合、特にファイルの範囲を絞り込んだ場合は、プランBに進みます。vim
(またはvi
)でファイルを開きます。 。エラーの前にあると思われる{
文字に移動し、%
と入力します。カーソルが、開始した}
と一致すると思われる{
にジャンプした場合は、次の{
に移動して繰り返します。開始した}
と一致しない{
にジャンプすると、これら2つの中括弧の間にエラーが発生します。移動しない場合は、現在の場所とファイルの末尾の間でエラーが発生します。ズームイン。
このアプローチは、C、C++、およびJava(それらのコンパイラーが十分に機能しない場合)のような言語のプログラムファイルに少し適しているかもしれませんが、シェルではかなりうまく機能するはずです。スクリプト。
最も簡単な方法は?使用しているシェルを認識しているシンタックスカラーリングのエディターを使用し、視覚的に検査します。ストリングカラーの大きなスワスを取得すると、見積もりを省略したことがわかります。ほぼすべてのまともなプログラミングエディターには構文の色分けがあります。
構文の色分けは時々それを誤解しますが、それは通常あなたのプログラムがあまりにも複雑で、人間もそれを誤解する可能性が高いことを示しています。
シェルプログラミングでは、"
、'
、および`
が区別しやすいフォントを使用してください。 ASCII引用符、‘’“”
など)のような非ASCII文字を誤って使用していないことを確認してください。
ShellCheck のような外部リンティングツールは問題を検出でき、bash
自体よりもメッセージと場所が優れている場合があります。
ほとんどがecho
ステートメントであり、途中に"${MY_ARRAY[1]"
があるプログラムの場合、ShellCheckは引用符で囲まれた文字列を解析できなかったことを通知します。さらに、問題を$
文字まで突き止め、パラメーターの展開に問題があることを示します。
ShellCheckは、Vim、Emacs、SublimeTextおよびAtom(とりわけ))で動作します。
G-Manのローテクソリューションを使用して、2000行以上のbashスクリプトで発生した大きな問題を解決できました。
シングルクォートに対するG-Manの答えより奇数のダブルクォートに対して同じことをする次の行を追加するだけです。
tr -cd "\"\n" < my_script.sh | awk 'length%2==1 {print NR, $0}'
ところで、shellcheck.netは非常に優れており、すべての優れたスクリプトがそれを通過するはずです。