web-dev-qa-db-ja.com

IF ... OR IF ... Windowsバッチファイル内

WindowsバッチファイルにIF OR IF条件ステートメントを記述する方法はありますか?

例えば:

IF [%var%] == [1] OR IF [%var%] == [2] ECHO TRUE
76
Mechaflash

Zmbqソリューションは優れていますが、FOR DO(...)ループのようなコードブロック内など、すべての状況で使用できるわけではありません。

別の方法は、インジケータ変数を使用することです。未定義になるように初期化してから、OR条件のいずれかが真である場合にのみ定義します。次に、IF DEFINEDを最終テストとして使用します-遅延拡張を使用する必要はありません。

FOR ..... DO (
  set "TRUE="
  IF cond1 set TRUE=1
  IF cond2 set TRUE=1
  IF defined TRUE (
    ...
  ) else (
    ...
  )
)

1番目の条件が真である場合、arasmussenがわずかに速く実行される可能性があるという理由で使用するELSE IFロ​​ジックを追加できますが、私は気にしません。

補遺-これは OR IFステートメントのWinXPバッチスクリプト

最終補遺-変数がリストのいずれかであるかどうかをテストするためのお気に入りのテクニックを忘れてしまった値の。許容値の配信リストを含むテスト変数を初期化し、検索と置換を使用して、変数がリスト内にあるかどうかをテストします。これは非常に高速で、任意の長いリストに最小限のコードを使用します。遅延拡張(またはCALL %% VAR %%トリック)が必要です。また、テストはCASE INSENSITIVEです。

set "TEST=;val1;val2;val3;val4;val5;"
if "!TEST:;%VAR%;=!" neq "!TEST!" (echo true) else (echo false)

VARに=が含まれている場合、上記は失敗する可能性があるため、テストは絶対確実ではありません。

VARの現在の値にアクセスするために遅延拡張が必要な​​ブロック内でテストを行う場合

for ... do (
  set "TEST=;val1;val2;val3;val4;val5;"
  for /f %%A in (";!VAR!;") do if "!TEST:%%A=!" neq "!TEST!" (echo true) else (echo false)
)

VAR内の期待値によっては、「delims =」などのFORオプションが必要になる場合があります

上記の戦略は、VARで=を使用しても、もう少しコードを追加することで信頼性を高めることができます。

set "TEST=;val1;val2;val3;val4;val5;"
if "!TEST:;%VAR%;=!" neq "!TEST!" if "!TEST:;%VAR%;=;%VAR%;"=="!TEST!" echo true

しかし、インジケータ変数を追加しない限り、ELSE句を提供する機能は失われています。コードは少し「ugい」ように見え始めましたが、VARが大文字と小文字を区別しない任意の数のオプションのいずれかであるかどうかをテストするための最良のパフォーマンスの信頼できる方法だと思います。

最後に、値ごとに1つのIFを実行する必要があるため、少し遅いと思う単純なバージョンがあります。 Aaciniは、前述のリンクの受け入れられた回答へのコメントでこのソリューションを提供しました

for %%A in ("val1" "val2" "val3" "val4" "val5") do if "%VAR%"==%%A do echo true

値のリストに*または?を含めることはできません文字、および値と%VAR%に引用符を含めることはできません。 %VAR%にもスペースまたは^&などの特殊文字が含まれている場合、引用符で問題が発生します。このソリューションのもう1つの制限は、インジケーター変数を追加しない限り、ELSE句のオプションを提供しないことです。利点は、IF /Iオプションの有無に応じて、大文字と小文字が区別される場合と区別されない場合があります。

84
dbenham

そうは思いません。同じラベルに2つのIFとGOTOを使用するだけです。

IF cond1 GOTO foundit
IF cond2 GOTO foundit

ECHO Didn't found it
GOTO end

:foundit
ECHO Found it!

:end
45
zmbq

この投稿をありがとう、それは私を大いに助けました。

Dunnoが助けになればいいのですが、私は問題を抱えていて、あなたのおかげで、このブール等価性に基づいてそれを解決する別の方法だと思いました。

「A or B」は「not(not A and not B)」と同じです

したがって:

IF [%var%] == [1] OR IF [%var%] == [2] ECHO TRUE

になる:

IF not [%var%] == [1] IF not [%var%] == [2] ECHO FALSE
6
Cactus

この質問が少し古い場合でも:

if cond1 or cond 2を使用する場合は、複雑なループなどを使用しないでください。

単純にifsと組み合わせたgotoの両方を提供します-これは暗黙的なORです。

//thats an implicit IF cond1 OR cond2 OR cond3
if cond1 GOTO doit
if cond2 GOTO doit
if cond3 GOTO doit

//thats our else.
GOTO end

:doit
  echo "doing it"

:end

Gotoを使用せずに「インプレース」アクションを使用すると、すべての条件が一致する場合、アクションを3回実行できます。

5
dognose

ただし、バッチにはIF <arg> ORまたはElifまたはELSE IFはありません...

他のIFを前のIFのELSE内にネストしてみてください。

IF <arg> (
    ....
) ELSE (
    IF <arg> (
        ......
    ) ELSE (
        IF <arg> (
            ....
        ) ELSE (
    )
)
2

IFを間接的に使用することで目標を達成できます。

以下は、一貫性のないラベルとGOTOなしで、CMDバッチで非常に簡潔かつ論理的に記述できる複雑な式の例です。

()括弧の間のコードブロックは、(哀れな)種類のサブシェルとしてCMDによって処理されます。ブロックから出てくる終了コードはすべて、ブロックが大きなブール式で再生する真/偽の値を決定するために使用されます。これらのコードブロックを使用して、任意の大きなブール式を作成できます。

簡単な例

各ブロックは、式全体の値が決定されるか、コントロールが飛び出すまで(例:GOTOを介して)、true(ブロック内の最後のステートメントが実行された後ERRORLEVEL = 0)に解決されます:

 ((DIR c:\xsgdde /w) || (DIR c:\ /w)) && (ECHO -=BINGO=-)

複雑な例

これにより、最初に発生した問題が解決されます。各ブロックで複数のステートメントが可能ですが、|| || ||可能な限り読みやすいように、簡潔であることが望ましいです。 ^はCMDバッチのエスケープ文字です。行末に配置すると、EOLをエスケープし、CMDに次の行のステートメントの現在のバッチの読み取りを続行するよう指示します。

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION

(
    (CALL :ProcedureType1 a b) ^
        || (CALL :ProcedureType2 sgd) ^
            || (CALL :ProcedureType1 c c)
) ^
    && (
        ECHO -=BINGO=-
        GOTO :EOF
    )
ECHO -=no bingo for you=-
GOTO :EOF

:ProcedureType1
    IF "%~1" == "%~2" (EXIT /B 0) ELSE (EXIT /B 1)
GOTO :EOF (this line is decorative as it's never reached)

:ProcedureType2
    ECHO :ax:xa:xx:aa:|FINDSTR /I /L /C:":%~1:">nul
GOTO :EOF
2
bogdan

単純な「FOR」を1行で使用して、「または」条件を使用できます。

FOR %%a in (item1 item2 ...) DO IF {condition_involving_%%a} {execute_command}  

あなたのケースに適用:

FOR %%a in (1 2) DO IF %var%==%%a ECHO TRUE
2
Apostolos

ORロジックを評価して単一の値を返す関数を使用することができます。

@echo off
set var1=3
set var2=5
call :logic_or orResult "'%var1%'=='4'" "'%var2%'=='5'"
if %orResult%==1 ( 
    echo At least one expression is true
) ELSE echo All expressions are false
exit /b

:logic_or <resultVar> expression1 [[expr2] ... expr-n] 
SETLOCAL
set "logic_or.result=0"
set "logic_or.resultVar=%~1"

:logic_or_loop 
if "%~2"=="" goto :logic_or_end 
if %~2 set "logic_or.result=1"
SHIFT 
goto :logic_or_loop 

:logic_or_end 
( 
  ENDLOCAL 
  set "%logic_or.resultVar%=%logic_or.result%"
  exit /b
) 
1
jeb
If %x%==1 (
If %y%==1 (
:: both are equal to 1.
)
)

これは、複数の変数が値と等しいかどうかを確認するためのものです。どちらの変数もここにあります。

If %x%==1 (
:: true
)
If %x%==0 (
If %y%==1 (
:: true
)
)
If %x%==0 (
If %y%==0 (
:: False
)
)

私は頭の中でそれを考えました。もっとコンパクトにできました。

1
coltonon

私はこの質問が古いことを知っていますが、同じ質問をしているときに他の誰か(私のような人)がこのスレッドを見つけた場合に備えて、別の解決策を投稿したいと思いました。変数をエコーし​​、findstrを使用して検証することで、OR演算子の欠如を回避することができました。

for /f %%v in ('echo %var% ^| findstr /x /c:"1" /c:"2"') do (
    if %errorlevel% equ 0 echo true
)
1
AKAJim

Dbenhamの答えはかなり良いですが、チェックしている変数がenvironment変数でない場合、IF DEFINEDに依存することで多くの問題が発生する可能性があります。スクリプト変数はこの特別な扱いを受けません。

これは滑edで文書化されていないBSのように思えるかもしれませんが、IF /?を使用してIFの単純なシェルクエリを実行すると、

DEFINED条件は、環境変数名を受け取り、環境変数が定義されています。

この質問への回答に関して、一連の評価の後に単純なフラグを使用するだけではない理由はありますか?基本的なロジックと読みやすさの両方の点で、これは最も柔軟なORチェックのようです。例えば:

Set Evaluated_True=false

IF %condition_1%==true (Set Evaluated_True=true)
IF %some_string%=="desired result" (Set Evaluated_True=true)
IF %set_numerical_variable% EQ %desired_numerical_value% (Set Evaluated_True=true)

IF %Evaluated_True%==true (echo This is where you do your passing logic) ELSE (echo This is where you do your failing logic)

明らかに、それらはどんな種類の条件付き評価でもかまいませんが、私はほんのいくつかの例を共有しています。

すべてを1行で記述したい場合は、次のように&&で連鎖させることができます。

Set Evaluated_True=false

IF %condition_1%==true (Set Evaluated_True=true) && IF %some_string%=="desired result" (Set Evaluated_True=true) && IF %set_numerical_variable% EQ %desired_numerical_value% (Set Evaluated_True=true)

IF %Evaluated_True%==true (echo This is where you do your passing logic) ELSE (echo This is where you do your failing logic)
0

働くために存在したことはありません。

存在しない場合はg:xyz/what goto h:を使用します。それ以外の場合はxcopy c:current/files g:bu/current修飾子/ aなどがあります。ショップのラップトップ。そしてオフィスのコンピューター。私はそこにいません。

Windows XP上で動作するバッチファイルを取得したことがない

0
user8865291