このように単純な「if」が機能しないのはなぜですか?

このように単純な「if」が機能しないのはなぜですか?

これは私のスクリプトです。

if [[ "$(echo "$2" | sed 's/.two//g')" == "load" ]] && [[ "$1" == "Decrypt" ]] || [[ "$(echo "$2" | sed 's/.two//g')" == "load" ]] && [[ "$1" == "Encrypt" ]] 
then
    key=aNXlye1tGbd0uP
else
    if [ -z "$key" ]
    then
        key="$2"
    fi
fi

2番目のパラメータを見つけて電位を取り除き、それと比較し.twoloadそうであればにload設定する必要があります。しかし、これはうまくいきません。実行してみるとこんな感じです。keyaNXlye1tGbd0uP

pskey Decrypt load (some string)

これは次の出力ですbash -x

++ echo load
++ sed s/.two//g
+ [[ load == \l\o\a\d ]]
+ [[ Decrypt == \D\e\c\r\y\p\t ]]
+ [[ Decrypt == \E\n\c\r\y\p\t ]]
+ '[' -z '' ']'
+ key=load

しかし、次のものを取り除くとうまく[[ "$1" == "Decrypt" ]]いきます。その行に問題がありますか?

答え1

私が正しく理解した場合は、次のようなものを探しています。

if [[ "$(echo "$2" | sed 's/.two//g')" == "load" && "$1" == "Decrypt" ]] || 
   [[ "$(echo "$2" | sed 's/.two//g')" == "load" && "$1" == "Encrypt" ]]
then
    ...
fi

次のようにすべてを簡素化することもできます。

 if [[ "$(echo "$2" | sed 's/.two//g')" == "load" && "$1" =~ (De|En)crypt ]]; then ...

答え2

terdonの声明は、「これは「単純さ」とは離れていますif。」 〜のようにジョン・クーゲルマンは次のように指摘した。、同じ優先順位を持ち、左から右に処理されます  &&||BinaryZebraがこのアイデアを提案しました。ブール式をカスケードifステートメントに変換します。 「単純化」しようとする

A&&Bの場合||
それから
        結果= 0
その他
        結果= 1
フィリピン諸島

はい

もし
それから
        Bラーメン
        それから
                もしD                                        
                それから
                        結果= 0
                その他
                        結果= 1
                フィリピン諸島
        その他
                もしC
                それから
                        もしD
                        それから
                                結果= 0
                        その他
                                結果= 1
                        フィリピン諸島
                その他
                        結果= 1
                フィリピン諸島
        フィリピン諸島
その他
        もしC
        それから
                もしD
                それから
                        結果= 0
                その他
                        結果= 1
                フィリピン諸島
        その他
                結果= 1
        フィリピン諸島
フィリピン諸島

非常に遠く簡単に始めましょう。上記のように動作しない理由は、(表示された行で)AとBの両方がtrueの場合、D([[ "$1" == "Encrypt" ]])をテストし続けるためです。

BinaryZebraが示しているが、言及していないように、できるたとえば、sh / bashスクリプトに数学表記を使用できます。

if(A&&B)||
それから

または少し単純化されたコードバージョンでは

もし[["$2"=="読み込み"]] && [["$1"=="復号化]]])  ||  [["$2"=="読み込み中"]] && [["$1"=="暗号化"]])
それから

その特徴は、括弧内のコードがサブシェルで実行されることです。これが問題であれば、中かっこを代わりに使用できます。

もし{[["$2"=="読み込み"]] && [["$1"=="復号化]]];  ||  {[["$2"=="読み込み中"]] && [["$1"=="暗号化"]];
それから

前に1つ(オプションでスペースで区切って)、;前、後、後にスペースを含める必要があります。}{}

もちろん、他の回答で提案された技術を使用する必要があります。単純化するあなたのテストです。いいえ同じテストを2回実行します$2

関連:パイプとリダイレクトと分離、結合などのバインディングの優先順位は何ですか?そして「if」が不要な場合はいつですか?

答え3

コードから:

if    [[ "$(echo "$2" | sed 's/.two//g')" == "load" ]] &&
      [[ "$1" == "Decrypt" ]]                          ||
      [[ "$(echo "$2" | sed 's/.two//g')" == "load" ]] &&
      [[ "$1" == "Encrypt" ]] 

sed呼び出しは次のように単純化できます。${2%?two}if置換は変数の末尾にあります$2。ドット(.)は、パターンの疑問符(?)に対応するsedの「すべての文字」を意味することを理解してください(@terdonに感謝します)。すべてのアイテムを交換する必要がある場合は、次のものを使用する必要があり.twoます"${2//?two}"。次に、次のような短いバージョンを取得します。

if [[ "${2//?two}" == "load" ]]  &&  [[ "$1" == "Decrypt" ]]  ||
   [[ "${2//?two}" == "load" ]]  &&  [[ "$1" == "Encrypt" ]] 

これは何してるのif A && B || C && D

Aがtrueの場合(Load = Load)、Bが実行されます。 Bがtrue(Decrypt = Decrypt)の場合は、
次の構文(C)をスキップしてD(Decrypt = Encrypt)を実行します。結果(最後に実行されたコマンド)は値です。それから実行してください...||

false
else

私はあなたがif ( A && B ) || ( C && D )asとA同じでCあり、まったく同じであることを意味すると思いますif ( A && B ) || ( A && D )。これは単純化することができます(使用して財産を分配する)到着
if A && ( B || D )

if      [[ "${2//?two}" == "load" ]] &&
      ( [[ "$1" == "Decrypt" ]]   ||  [[ "$1" == "Encrypt" ]]  );
then
      key=aNXlye1tGbd0uP
else
      if    [ -z "$key" ]
      then  key="$2"
      fi
fi

"$key" のテストは-z簡単な拡張に縮小できます: key="${key:-$2}"

そして、おそらく次のように読みやすくなります(IMO)。

if A; then
      if   B || D; then

翻訳するとこんな感じです。

if           [[ "${2//?two}" == "load" ]]
then   if    [[ "$1" == "Decrypt" ]]   ||  [[ "$1" == "Encrypt" ]]
       then  key=aNXlye1tGbd0u
       else  key="${key:-$2}"
       fi
else         key="${key:-$2}"
fi

あるいは、@terdonのアイデアを使って次のように書くことができます。

if           [[ "${2//?two}" == "load" ]] &&
             [[ "$1" =~ (De|En)crypt ]]
then         key=aNXlye1tGbd0u
else         key="${key:-$2}"
fi

これも同じです。

if       [[  ( "${2//?two}" == "load" ) &&
             ( "$1" =~ (De|En)crypt )
         ]]
then         key=aNXlye1tGbd0u
else         key="${key:-$2}"
fi

括弧は必ずしも必要ではありませんが、[[テスト内でスペース(タブ、スペース、改行)および括弧を追加してテストに構造を提供できるというアイデアを強化するために追加されました。これはテストで異なる動作をしました[

答え4

最初:

[[ $1:$2 =~ ^(En|De)crypt:(.two)*load(.two)*$ ]] && echo conditions met

しかし、ifブール論理は反対です。

#sed    #En=$1   #De=$1
true  && false || true    # passes your logic
true  && true  || NA      # passes your logic
false && NA    || false   # fails  your logic
false && NA    || true    # fails  your logic

2番目は&&要因ではないので、ここでは省略されています。その結果は常に最初のものと同じです。この論理チェーンでは、それは役に立たないものです。

これはあまり効果的ではありません。失敗したケースはあなたの声明を壊します。最初のテストが偽の場合は、(De | En)cryptテストの代わりにOR返しを実行します。実際、最初のものはショートのために発生しません。ジム返品。したがって、最初にORを実行して実際にテストするまで、高価なコマンドの置き換えを遅らせて段落を利用する必要があります。

#En=$1  #De=$1   #sed
false || false && NA
false || true  && false
false || true  && true
true  || NA    && false
true  || NA    && true

これらすべてがロジックを通過します。最初の両方のステートメントが偽の場合、コマンドの置き換えは試行されません。

これはcase、次のように移植可能ですexpr

case  ${2%oad*}:${1%crypt}  in
(:${key:=$2}*|*ad*|*:"$1")  ;;
(*l:De|*l:En)  expr " $2" :  \
" \(\(.two\)*\(load\)*\)*$" &&
     key=aNXlye1tGbd0uP
esac >/dev/null   

そしてif

if   [ Encrypt = "$1" -o Decrypt = "$1" ] &&
     expr " $2" : " \(.two\)*load\(.two\)*$"
then key=$newkey
else key=${key:-$2}
fi   >/dev/null

ただexpr、それ&&||ifあなたにあまり役に立たないので:

expr   > /dev/null       \
 "${#1} ${1%crypt}  $2" :\
 "7 \(\(De\)*\(En\)*\) ""\
 \(.two\)*load\(.two\)*$" &&
key=$newkey || key=${key:-$2}

おそらく次のようなものがありますgrep

grep -xqE '(En|De)crypt:(.two)*load(.two)*' \
<<VAR &&   key=$newkey || key=${key:-$2}
${1##*:*}:$2
VAR

関連情報