web-dev-qa-db-ja.com

場合のifステートメントの変換

現在、パフォーマンスの目的でスクリプトの変更をテストしています。具体的には、ifcaseステートメントに変更したいと思います。

ただし、シェルプログラミングに慣れていないので、次のタイプのステートメントに固執しています。

if [ "$A" == "x" -a "$B" == "y" ] 
    then
        let a=a+1
fi 

私はこれを試しましたが、うまくいきませんでした:

case "$A$B" in
    "x""y") let a=a+1
;;
esac

何が間違っていたのですか?

また、caseステートメントで「!=」を管理することは可能ですか?といった:

if [ "$A" == "x" -a "$B" != "y" ] 
then
    let a=a+1
fi 
1
Matieu

あなたのcaseの例は私にとってはうまくいきますが、ABなので、たとえばAxyで、Bが空の場合も、パターンは一致します。 (真ん中の二重引用符は冗長だと思います。)caseは、パターンと比較するために1つのWordしか取りません。連結する場合を除いて、複数の変数を比較することはできません。

標準のtestまたは[コマンドでは、比較演算子は=です。 ==は一部のシステムで機能しますが、すべてではありません。また、-aを使用して条件を組み合わせると、少なくとも-nのような条件では問題が発生します。 ( この質問 を参照)。 if [ "$A" = x ] && [ "$B" = y ] ; then ...を使用することをお勧めします。

caseを反転する場合は、ターゲット文字列以外のすべてに一致するパターンを考え出す必要があります。 extglob in Bash その他は、以下を除くすべてに一致させることができます。

case $B in !(y) ) echo not y ;; esac

これがないと、パターンを反転するためにさらに作業を行うか、最初のパターンが文字列に一致し、後でデフォルトの一致が実際のアクションを実行する複数のパターンを使用する必要があります。

case $B in ??*) echo not y ;; [^y]) echo also not y ;; esac

case $B in y) ;; *) echo still not y ;; esac

(特に最初のものについては保証はありません。率直に言って、これを行うという考え全体は恐ろしいようです。)

とにかく、パフォーマンス上の理由について言及したので、シェルの代わりにPerlまたはPythonに変更することを検討してください。単純な比較のためではなく、外部プログラム(grepsedcut、またはjqなど)。また、パフォーマンス最適化の最初のルール:差を測定します。

2
ilkkachu
#  $A = "x" && $B = "y"
case ${A:--}/${B:--} in 'x/y' ) let a=a+1;; esac

# $A = "x" && $B != "y"
case $A in 'x' ) case $B in '' | ??* | [!y] ) let a=a+1;; esac;; esac
0
user218374