Bashで単純なループを試すときの問題

Bashで単純なループを試すときの問題
#!bin/sh
a=0
while["$a -lt 50"]
do
echo $a
a='expr $a+1'
done

私は無限のエコーを得ましたexpr $a+1。私は何が間違っていましたか?

答え1

スクリプトに構文エラーがあります。以下を使用して、シェルスクリプトに問題のある構造があるかどうかを確認できます。住宅検査オンライン。

これはあなたに言うでしょう

Line 3:
while["$a -lt 50"]
^-- SC1009: The mentioned parser error was in this while loop.
     ^-- SC1035: You need a space after the [ and before the ].
     ^-- SC1069: You need a space before the [.
     ^-- SC1073: Couldn't parse this test expression.
                  ^-- SC1020: You need a space before the ].
                  ^-- SC1072: Missing space before ]. Fix any mentioned problems and try again.

変更によるスペースのトラブルシューティング

while["$a -lt 50"]

入力する

while [ "$a -lt 50" ]

代わりに、以下が提供されます。

Line 3:
while [ "$a -lt 50" ]
           ^-- SC2157: Argument to implicit -n is always true due to literal strings.

Line 6:
a='expr $a+1'
  ^-- SC2016: Expressions don't expand in single quotes, use double quotes for that.

報告された最初の問題は文字列に関するものです"$a -lt 50"。実際、ここではそのような文字列が欲しくありません"$a" -lt 50。ところで、文字列は常に「true」なのでこれがループが無限の理由です。(構文エラーが修正された場合)

2番目の問題は、チェッカーが$a一重引用符で囲まれた文字列内の変数を検出するために発生します。これはその値には拡張されません(そのため、印刷された文字列は次のようになります。expr $a+1)。解決策は二重引用符に変更しないことです。これは同じ文字列を提供しますが、値は拡張されます。コマンドを実行したいですexpr

一重引用符をバックティックに変更するだけです。

これでスクリプトは次のようになります。

#!bin/sh
a=0
while [ "$a" -lt 50 ]
do
echo $a
a=`expr $a+1`
done

...そしてShellCheckはまだ満足していません。

Line 6:
a=`expr $a+1`
  ^-- SC2006: Use $(..) instead of legacy `..`.
   ^-- SC2003: expr is antiquated. Consider rewriting this using $((..)), ${} or [[ ]].

$( ... )新しいシェルコードは実際にはバックティックの代わりにバックティックを使用する必要があります。また、expr古い使用法に関する警告も表示されます。

この行は次のように書き直すことができます。

a="$(( a + 1 ))"

最終バージョン(インデントと行の修正を含む#!):

#!/bin/sh

a=0
while [ "$a" -lt 50 ]; do
  echo $a
  a="$(( a + 1 ))"
done

bashまたは、ksh93算術評価用のバージョンを使用して(( ... ))コードをさらに短縮します。

#!/bin/bash

a=0
while (( a < 50 )); do
  echo "$(( a++ ))"
done

答え2

オリジナルを編集してください

#!bin/sh
a=0
while [ "$a" -lt "50" ] # mind the spaces and double quote the variable
do
echo "$a"
a=`expr $a + 1` # replace single quotes with backticks, mind the space between $a and 1
done

改善する

#!bin/bash  # Why not put bash here? sh may not always be linked to bash
a=0
while [ "$a" -lt "50" ] # mind the spaces and double quote the variable
do
echo "$a"
a=$(expr $a + 1) # replace legacy backticks with $()
# Or better you can even use double parenthesis which allows you do
# (( a++ )) , note the C style increment operator here
done

ノートスクリプトを確認するには、次のようにします。[シェルチェック]

答え3

または常にforループを使用してください。

for ((a=0;a < 50; ++a))
do echo $a
done

迅速かつ簡単です。実行にバックティックは必要ありません。

答え4

#!bin/sh
a=0
while [ $a -lt 50 ]
do
  echo $a
  a=$((a+1))
done

これにはすべてのスペースが必要です。

関連情報