変数が存在し、等しくない場合に効率的に比較する

変数が存在し、等しくない場合に効率的に比較する

スクリプトの構文に問題がありますsh。Asus ルーター用のスクリプトを作成しました。スクリプトは完璧に動作します。しかし、次の行があります:

if [[ "$OldIP" && "$StartIP" != "$OldIP" ]]; then echo OK; fi

とが同じでないecho OK場合にのみ、これが真 (および ) になります。 この行は機能しますが、より効率的に実行できるようにしたいと思います。 変数には有効な IP アドレスが含まれています。$StartIP$OldIP

場合によっては、$OldIP何も割り当てられません (初期化されません)。ただし、$OldIP存在しない場合は、シェル内で同じではないことを意味します。

次のような行は実行したくありません:$OldIP存在しない場合は -> 異なるかどうかをテストし、実行しますecho OK

この行の意味は、a)$OldIP存在しない場合は終了、b)$OldIP存在する場合は異なるかどうかをテストして実行、となりますecho OK

"$OLDIP" &&だから、可能であれば、何らかの方法で削除したいです 。実際の問題ではありませんが、知りたいです :)

そうですね(ただし動作​​しません):

if [ [ "$OldIP" ] != "$StartIP" ]; then echo OK; fi

または

if [ $OldIP != "$StartIP" ]; then echo OK; fi

これは私が望むことをするが、古いIP空です(ただし正常に動作します)

その間

if [ "$OldIP" != "$StartIP" ]; then echo OK; fi

動作しますが、それを無視します古いIP空です

答え1

厳密に言えば、変数は、値が一度も割り当てられていない場合、または割り当てられている場合には存在しませんunset。値として空の文字列を持つ変数は存在する

標準パラメータ展開では、存在する場合(未設定または空ではない場合)に${variable+value}文字列が置き換えられます。これは、次のように存在をテストするために使用できます。valuevariable

if [ "${OldIP+x}" = "x" ] && [ "$OldIP" != "$StartIP" ]; then
    # code
fi

OldIPが存在するかどうかをテストするにはbash、次の-vテストを使用します。

 if [[ -v OldIP ]] && [[ "$OldIP" != "$StartIP" ]]; then
     # code
 fi

これは、以前に設定されていた場合(空の文字列に設定されていた場合でも)にのみ$OldIP、と間の文字列比較を実行します。テストでは、$StartIPOldIP-v名前変数の。

答え2

あなたのスクリプトは現状でもかなり効率的だと思います。確かに、これに多くのサイクルを費やす必要はありません。

ロジックを記述する別の方法:

{ test -n "$OldIP" || test "$StartIP" != "$OldIP"; } && echo OK

これは、「OldIP が設定されている場合、または OldIP と StartIP が異なる場合は、OK をエコーし​​ます」という意味です。

は、 で読むことができる[別の名前であることを覚えておいてください。test(1)man 1 test

編集: Gilles が指摘したように、( ... )必要のないサブシェルを作成しないように注意してください。

{ ... ; }新しいシェルを実行せずにコマンドをグループ化するために使用できます。

簡単な参考資料:http://www.gnu.org/software/bash/manual/html_node/コマンドグループ化.html

答え3

これはあなたが求めていることを実行します:

[ "${OldIP:-"$StartIP"}" != "$StartIP" ] && echo "OK"

これも同様に(より複雑です):

${OldIP:+false} || { [[ $OldIP != $StartIP ]] && echo "OK"; }

答え4

を使用している場合はbash、デフォルトの置換を使用できます。

[[ "${OldIP:=oldunset}" != "${StartIP?StartUnset" ]] && echo "OK"

構文は、 の現在の値、または変数が設定されていないか null の場合は指定されたデフォルト (この場合は ) の${var:-def}いずれかに評価されます。変数の値 (存在する場合) は変更されません。$vardef

設定されていないか null の場合、構文は${var?message}エラー コード 1 とメッセージで終了します。message$var

明示的に -compatible テストが必要な場合はtest、次のようにします。

[ ! -z "$OldIP" -a "$OldIP" != "$StartIP" ] && echo "OK"

関連情報