web-dev-qa-db-ja.com

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

shスクリプト構文に問題があります。 Asusルーター用のスクリプトを書きました。スクリプトは完全に機能します。しかし、私はこの行を持っています:

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

echo OK$StartIPが同じでない場合にのみ、true(および$OldIPを実行)にする必要があります。ラインは機能しますが、より効率的に実行されることを望んでいます。変数には有効なIPアドレスが含まれています。

場合によっては、$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

これは私がやりたいことをしますが、OldIPが空の場合に文句を言います(ただし、問題なく動作します)

ながら

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

動作しますがOldIPが空であることを無視します

4
Pila

厳密に言うと、値が割り当てられたことがない場合、またはunsetであった場合、変数は存在しません。値として空の文字列を持つ変数exists

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

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

OldIPbashに存在するかどうかをテストするには、-vテストを使用します。

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

これにより、$OldIP$StartIPの文字列比較は、OldIPが以前に設定されている場合にのみ実行されます(空の文字列に設定されている場合でも)。 -vテストは、変数のnameを取ることに注意してください。

2
Kusalananda

私はあなたのスクリプトがそのままかなり効率的だと思います。あなたは確かにこれに多くのサイクルを費やしていない。

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

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

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

_[_は、_man 1 test_で参照できるtest(1)の別名です。

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

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

簡単なリファレンス: http://www.gnu.org/software/bash/manual/html_node/Command-Grouping.html

0
ssh2ksh

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

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

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

シンタックス${var?message}は、$varが設定されていないかnullの場合、messageのメッセージとともにエラーコード1で終了します。

testと互換性のあるテストが明示的に必要な場合、これを行うことができます:

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

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

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

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

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