予期しないトークン `fi` の近くに構文エラーがあります

予期しないトークン `fi` の近くに構文エラーがあります

必ずしも答えが欲しいわけではありませんが、誰かが文献や例を示してくれると、理解したいと思うのです。

スクリプトを実行すると、次のエラーが表示されます:

予期しないトークンの近くに構文エラーがありますfi

ifステートメントにコメントを付けてifecho "$NAME"内の名前を表示する を追加することで、問題はステートメントにあると推測しました/etc/

変更を加えて、#からとを削除しif、に fi追加した場合、上記の構文エラーが発生します。その間にを追加しました。また、次の行に移動しましたが、解決されませんでした。#wc -c "$NAME";]then

#!/bin/bash
for NAME in /etc/*
do

     if [ -r "$NAME" -af "$NAME" ] then
          wc -c "$NAME"
     fi
done

答え1

if、、、、などthenのキーワードは、シェルがコマンド名を期待する場所に置く必要があります。そうでない場合は、通常の単語として扱われます。たとえば、elsefiforcase

echo if

を印刷するだけでif、条件付き命令は開始されません。

したがって、

if [ -r "$NAME" -af "$NAME" ] then

単語はthenコマンドの引数です[(実行された場合、コマンドはこれについて文句を言うでしょう)。シェルは を探し続けthenfiコマンドの位置に を見つけます。ifがまだ を探しているためthen、 はfi予期されておらず、構文エラーが発生します。

キーワードとして認識されるように、の前にコマンドターミネータを置く必要がありますthen。最も一般的なコマンドターミネータは改行ですが、 の前にはthenセミコロン (改行とまったく同じ意味) を使用するのが一般的です。

if [ -r "$NAME" -af "$NAME" ]; then

または

if [ -r "$NAME" -af "$NAME" ]
then

これを修正すると、コマンド[が理解できないため、別のエラーが発生します-af。おそらく、

if [ -r "$NAME" -a -f "$NAME" ]; then

テスト コマンドはオプションのように見えますが、このようにまとめることはできません。これらはコマンドの演算子であり[、それぞれが別の単語である必要があります (do や[など])。

ちなみに、[ -r "$NAME" -a -f "$NAME" ]うまくいきますが、どちらかを書くことをお勧めします

[ -r "$NAME" ] && [ -f "$NAME" ]

または

[[ -r $NAME && -f $NAME ]]

コマンドは演算子とオペランドを簡単に区別できない[ … ]ため、条件文はシンプルにしておくのが最善です。 が演算子のように見え、演算子が有効な位置に出現すると、演算子として解析される可能性があります。 この回答で見られるような単純なケースではこのようなことは起こりませんが、より複雑なケースではリスクがあります。 を別々に呼び出してシェルの論理演算子を使用することで、この問題を回避できます。[$NAME[

2番目の構文は、[[ … ]]bash(およびkshとzsh、ただしshにはない)に存在する条件構文を使用します。この構文は特別な構文ですが、[他のコマンドと同様に解析されるため、 inside のようなものを使用でき、一部の文字列演算子( 、、 )&&の引数を除いて変数を引用符で囲む必要はありません(===!==~二重引用符はいつ必要ですか?詳細については)。

答え2

変更点は以下のとおりです

if [ -r "$NAME"-a -f["$NAME"];それから
# ^^^^^ ^
     wc -c "$NAME"
フィ

ifブロック内のすべてのコマンドを削除したい場合は、少なくともコロンを追加する必要があります。

if [ -r "$NAME" -a -f "$NAME" ]; then
    :
fi

または1行バージョン

if [ -r "$NAME" -a -f "$NAME" ]; then :; fi

答え3

すでに他の人が指摘していますが、公式の参考資料を探しているならRTMS

if リスト; then リスト; [ elif リスト; then リスト; ] ... [ else リスト;] fi

if リストが実行されます。終了ステータスが 0 の場合、then リストが実行されます。それ以外の場合、各 elif リストが順番に実行され、終了ステータスが 0 の場合、対応する then リストが実行され、コマンドが完了します。それ以外の場合、else リストが実行されます (存在する場合)。終了ステータスは、最後に実行されたコマンドの終了ステータス、または条件が真と判定されなかった場合は 0 になります。

あなたは;

そして、listは、man test

関連情報