-eqを使用して文字列を比較すると、if文は[では機能しますが、[[反復]では機能しません。

-eqを使用して文字列を比較すると、if文は[では機能しますが、[[反復]では機能しません。

私のコード:

#!/bin/bash

x=${#}

for (( a=0; a<x; ++a)); do
   if [[ $1 -eq $1 ]] 2> /dev/null
   then
      variable[a]=${1}
      shift
   else
      echo "The argument $1 is NOT an integer. Aborting this"
      exit 1
   fi
done
TOTAL=0
for (( a=0; a<x; ++a)); do
      echo "TOTAL : ${TOTAL}"
      TOTAL=$((TOTAL+variable[a]))
done
echo "Everything accounted to $TOTAL"
exit 0

したがって、基本的にスクリプトの引数を取得して要約します。引数の1つが整数でない場合は、それを通知してスクリプトを終了する必要があります。

今起こるのは、パラメータの1つが整数ではないかどうかを知らせずに、単にスキップすることです。したがって、パラメーター123 123 123 asdtを指定すると、次の結果が得られます。

vagrant@localhost vagrant]$./super.sh 123 123 123 asdt
TOTAL : 0
TOTAL : 123
TOTAL : 246
TOTAL : 369
Everything accounted to 369
[07:43----------------------------------------
vagrant@localhost vagrant]$

しかし、これをこのように変えると:

for (( a=0; a<x; ++a)); do
   if [ $1 -eq $1 ] 2> /dev/null
   then

動作します。以下を取得します。

vagrant@localhost vagrant]$./super.sh 123 123 123 asdt
The argument asdt is NOT an integer. Aborting this
[07:44----------------------------------------
vagrant@localhost vagrant]$

なぜこれが起こるのですか?

答え1

これがBashの特別な点の1つです[[ .. ]][[ a -eq b ]]強制和は算術式で処理されabその中で文字列は変数名として処理されます。他の式も機能するので、次のようにすることができます。

$ a=2
$ [[ a -eq 1+1 ]] && echo yes
yes

一方、これは[一般的なコマンドであり、通常のコマンドと同じ構文に従います。外部バイナリとして実装することもできます。ここではそれを[見て、aそれが実際の整数ではないと文句を言うでしょう。

$ [ a -eq 2 ] && echo yes
bash: [: a: integer expression expected
$ /usr/bin/[ a -eq 2 ] && echo yes
/usr/bin/[: invalid integer ‘a’

ただ次のようなものを使用してください

a=asdf
if [[ $a = *[^0-9]* ]]; then
    echo "'$a' isn't an integer"
fi

または

a=asdf
case "$a" in 
    *[^0-9]*) echo "'$a' isn't an integer";;
esac

明らかにksh合算における算術評価は有効である。a1+1[ a -eq 1+1 ]

関連情報