web-dev-qa-db-ja.com

パラメータがバッチファイルで空かどうかをテストするための適切な方法は何ですか?

変数が設定されているかどうかをテストする必要があります。私はいくつかのテクニックを試しましたが、%1%1の場合のように"c:\some path with spaces"が引用符で囲まれていると失敗するようです。

IF NOT %1 GOTO MyLabel // This is invalid syntax
IF "%1" == "" GOTO MyLabel // Works unless %1 has double quotes which fatally kills bat execution
IF %1 == GOTO MyLabel // Gives an unexpected GOTO error.

このサイト によると、これらはサポートされているIF構文型です。それで、私はそれをする方法を見ません。

IF [NOT] ERRORLEVEL number command
IF [NOT] string1==string2 command
IF [NOT] EXIST filename command
183
blak3r

引用符の代わりに角括弧を使用してください。

IF [%1] == [] GOTO MyLabel

括弧は安全でない:大括弧のみを使用します。

252
Dan Story

あなたが使用することができます:

IF "%~1" == "" GOTO MyLabel

外側の引用符を削除します。一般に、変数にスペースが含まれていても機能するので、これは角括弧を使用するよりも信頼性の高い方法です。

127
jamesdlin

最良のセミソリューションの1つは、%1を変数にコピーして、delayedExpのように遅延展開を使用することです。どんなコンテンツに対しても常に安全です。

set "param1=%~1"
setlocal EnableDelayedExpansion
if "!param1!"=="" ( echo it is empty )
rem ... or use the DEFINED keyword now
if defined param1 echo There is something

これの利点はparam1を扱うことが絶対に安全であるということです。

また、param1の設定は、多くの場合、次のように機能します。

test.bat hello"this is"a"test
test.bat you^&me

しかし、それはのような奇妙な内容で失敗するでしょう

test.bat "&"^&

あなたが99%の防弾プルーフになりたいなら、あなたは読むことができます 奇妙なコマンドラインパラメータさえ受け取る方法?

31
jeb

IFから/?:

Command Extensionsが有効になっている場合、IFは次のように変更されます。

IF [/I] string1 compare-op string2 command
IF CMDEXTVERSION number command
IF DEFINED variable command

......

DEFINED条件は、環境変数名を取り、環境変数が定義されていればtrueを返す点を除いて、EXISTSと同じように機能します。

16
Andy Morris

バッチファイル内の変数をテストするには、 "IF DEFINED variable command"を使用します。

しかし、バッチパラメータをテストしたい場合は、面倒な入力を避けるために以下のコードを試してください( "1 2"やab ^> cdなど)。

set tmp="%1"
if "%tmp:"=.%"==".." (
    echo empty
) else (
    echo not empty
)
6
zackz

残念ながら、私は自分のものを書かなければならないという現在の答えにコメントしたり投票したりするのに十分な評判がありません。

もともとOPの質問は「パラメータ」ではなく「変数」と言っていましたが、特にこれがGoogleで空白の変数をテストする方法を探すための一番のリンクであったため、非常に混乱していました。私の最初の答え以来、Stephanは最初の質問を正しい用語を使用するように編集しました、しかし私の答えを削除するのではなく混乱を解決するためにそれを残すことにしました。

%1 ISは可変ではありません!IT ISコマンドラインパラメータ。

非常に重要な区別後に数字が付いた単一のパーセント記号は、変数ではなくコマンドラインパラメータを表します。

変数はsetコマンドを使用して設定され、前後2つのパーセント記号を使用して呼び出されます。例えば、%myvar%

空の変数をテストするには、「定義されていない」という構文を使用します(変数に対して明示的に指定するコマンドではパーセント記号は必要ありません)。次に例を示します。

set myvar1=foo  
if not defined myvar1 echo You won't see this because %myvar1% is defined.  
if not defined myvar2 echo You will see this because %myvar2% isn't defined.

(コマンドラインパラメータをテストしたい場合は、jamesdlinの回答を参照することをお勧めします。)

6
AutoMattTick

あなたが使用することができます

if defined (variable) echo That's defined!
if not defined (variable) echo Nope. Undefined.
3
noname

私は通常これを使います。

IF "%1."=="." GOTO MyLabel

%1が空の場合、IFは "。"を比較します。に。これはtrueと評価されます。

3
aphoria

以下のコードでテストしても大丈夫です。

@echo off

set varEmpty=
if not "%varEmpty%"=="" (
    echo varEmpty is not empty
) else (
    echo varEmpty is empty
)
set varNotEmpty=hasValue
if not "%varNotEmpty%"=="" (
    echo varNotEmpty is not empty
) else (
    echo varNotEmpty is empty
)
3
Kate

空の文字列はdouble-quotes/""のペアです。長さをテストするだけです。

set ARG=%1
if not defined ARG goto nomore

set CHAR=%ARG:~2,1%
if defined CHAR goto goon

それからdouble-quotesに対して2文字をテストします。

if ^%ARG:~1,1% == ^" if ^%ARG:~0,1% == ^" goto blank
::else
goto goon

これはあなたが遊べるバッチスクリプトです。私はそれが適切に空の文字列をキャッチすると思います。

これはほんの一例です。スクリプトに応じて上記の2つ(または3つ)のステップをカスタマイズする必要があります。

@echo off
if not "%OS%"=="Windows_NT" goto EOF
:: I guess we need enableExtensions, CMIIW
setLocal enableExtensions
set i=0
set script=%0

:LOOP
set /a i=%i%+1

set A1=%1
if not defined A1 goto nomore

:: Assumption:
:: Empty string is (exactly) a pair of double-quotes ("")

:: Step out if str length is more than 2
set C3=%A1:~2,1%
if defined C3 goto goon

:: Check the first and second char for double-quotes
:: Any characters will do fine since we test it *literally*
if ^%A1:~1,1% == ^" if ^%A1:~0,1% == ^" goto blank
goto goon

:goon
echo.args[%i%]: [%1]
shift
goto LOOP

:blank
echo.args[%i%]: [%1] is empty string
shift
goto LOOP

:nomore
echo.
echo.command line:
echo.%script% %*

:EOF

この拷問テストの結果:

.test.bat :: ""  ">"""bl" " "< "">"  (")(") "" :: ""-"  " "( )"">\>" ""
args[1]: [::]
args[2]: [""] is empty string
args[3]: [">"""bl" "]
args[4]: ["< "">"]
args[5]: [(")(")]
args[6]: [""] is empty string
args[7]: [::]
args[8]: [""-"  "]
args[9]: ["( )"">\>"]
args[10]: [""] is empty string

command line:
.test.bat :: ""  ">"""bl" " "< "">"  (")(") "" :: ""-"  " "( )"">\>" ""
3
user6801759

スクリプト1:

入力( "Remove Quotes.cmd" "これはテストです")

@ECHO OFF

REM Set "string" variable to "first" command line parameter
SET STRING=%1

REM Remove Quotes [Only Remove Quotes if NOT Null]
IF DEFINED STRING SET STRING=%STRING:"=%

REM IF %1 [or String] is NULL GOTO MyLabel
IF NOT DEFINED STRING GOTO MyLabel


REM   OR   IF "." equals "." GOTO MyLabel
IF "%STRING%." == "." GOTO MyLabel

REM GOTO End of File
GOTO :EOF

:MyLabel
ECHO Welcome!

PAUSE

出力(なし、%1は空白、空、またはNULLではありません):


上記のスクリプトを使用して、パラメータなしで( "Remove Quotes.cmd"を実行)1

出力(%1は空白、空、またはNULL):

Welcome!

Press any key to continue . . .

注:IF ( ) ELSE ( )ステートメント内に変数を設定した場合、それが "IF"ステートメントを終了するまでDEFINEDに使用することはできません( "Delayed Variable Expansion"が有効になっている場合を除く。パーセント "%"記号}。

例えば:

スクリプト2:

入力( "Remove Quotes.cmd" "これはテストです")

@ECHO OFF

SETLOCAL EnableDelayedExpansion

SET STRING=%0
IF 1==1 (
  SET STRING=%1
  ECHO String in IF Statement='%STRING%'
  ECHO String in IF Statement [delayed expansion]='!STRING!'
) 

ECHO String out of IF Statement='%STRING%'

REM Remove Quotes [Only Remove Quotes if NOT Null]
IF DEFINED STRING SET STRING=%STRING:"=%

ECHO String without Quotes=%STRING% 

REM IF %1 is NULL GOTO MyLabel
IF NOT DEFINED STRING GOTO MyLabel

REM GOTO End of File
GOTO :EOF

:MyLabel
ECHO Welcome!

ENDLOCAL
PAUSE

出力:

C:\Users\Test>"C:\Users\Test\Documents\Batch Files\Remove Quotes.cmd" "This is a Test"  
String in IF Statement='"C:\Users\Test\Documents\Batch Files\Remove Quotes.cmd"'  
String in IF Statement [delayed expansion]='"This is a Test"'  
String out of IF Statement='"This is a Test"'  
String without Quotes=This is a Test  

C:\Users\Test>  

注:文字列の内側から引用符も削除されます。

例(スクリプト1または2を使用):C:¥Users¥Test¥Documents¥Batch Files>「Remove Quotes.cmd」「これは「テスト」です。

出力(スクリプト2):

String in IF Statement='"C:\Users\Test\Documents\Batch Files\Remove Quotes.cmd"'  
String in IF Statement [delayed expansion]='"This is "a" Test"'  
String out of IF Statement='"This is "a" Test"'  
String without Quotes=This is a Test  

スクリプト2でパラメータを指定せずに( "Remove Quotes.cmd")を実行します。

出力:

Welcome!

Press any key to continue . . .
2
Mr. Rick

有効なスクリプトが多数あるため、ここでの回答に基づいてこの小さなバッチスクリプトを作成しました。あなたが同じフォーマットに従う限り、これに追加してください。

REM Parameter-testing

Setlocal EnableDelayedExpansion EnableExtensions

IF NOT "%~1"=="" (echo Percent Tilde 1 failed with quotes) ELSE (echo SUCCESS)
IF NOT [%~1]==[] (echo Percent Tilde 1 failed with brackets) ELSE (echo SUCCESS)
IF NOT  "%1"=="" (echo Quotes one failed) ELSE (echo SUCCESS)
IF NOT [%1]==[] (echo Brackets one failed) ELSE (echo SUCCESS)
IF NOT "%1."=="." (echo Appended dot quotes one failed) ELSE (echo SUCCESS)
IF NOT [%1.]==[.] (echo Appended dot brackets one failed) ELSE (echo SUCCESS)

pause
2

まとめると、

set str=%~1
if not defined str ( echo Empty string )

%1が ""または "または空の場合、このコードは"空の文字列 "を出力します。現在正しくないと思われる回答に追加しました。

2
GrayFace

使ってます!空の文字列チェックの場合は "の代わりに

@echo off
SET a=
SET b=Hello
IF !%a%! == !! echo String a is empty
IF !%b%! == !! echo String b is empty
0
Lin W

私は多くの問題を抱えていて、ネット上にはたくさんの答えがありました。ほとんどのものはほとんどのものに対して機能しますが、それぞれを破るコーナーケースが常にあります。
引用符があるとうまくいかないかもしれませんし、引用符がないとうまくいかないかもしれませんし、varにスペースがあると文法エラーになるかもしれません。他の技法では空の引用符のセットを 'defined'として渡すことができますが、それより巧妙なものでは後でelsename__を連鎖させることはできません。

ここに私が満足している解決策があります、あなたがそれがうまくいかないコーナーケースを見つけたら私に知らせてください。

:ifSet
if "%~1"=="" (Exit /B 1) else (Exit /B 0)

そのサブルーチンをあなたのスクリプトの中、あるいはそれ自身の.batの中に持っていても、うまくいくはずです。
それで、あなたが(疑似で)書きたいのならば:

if (var)
then something
else somethingElse

あなたは書ける:

(Call :ifSet %var% && (
    Echo something
)) || (
    Echo something else
)

それは私のすべてのテストでうまくいった:

(Call :ifSet && ECHO y) || ECHO n
(Call :ifSet a && ECHO y) || ECHO n
(Call :ifSet "" && ECHO y) || ECHO n
(Call :ifSet "a" && ECHO y) || ECHO n
(Call :ifSet "a a" && ECHO y) || ECHO n

エコーされるnname__、yname__、nname__、yname__、yname__


その他の例

  • ifname__をチェックしたいだけですか? Call :ifSet %var% && Echo set
  • そうでなければ(他の人だけ)? Call :ifSet %var% || Echo set
  • 渡された引数を確認します。正常に動作します。 Call :ifSet %1 && Echo set
  • スクリプトや重複コードを詰まらせたくなかったので、それを独自のifSet.batに入れますか?問題ありません:((Call ifSet.bat %var%) && Echo set) || (Echo not set)
0
Hashbrown

私は1ヶ月も経たないうちに入りました(8年前に聞かれましたが)...私は彼/彼女が今バッチファイルを超えて動いていることを願っています。 ;-)私はいつもこれをしていました。しかし、最終的な目標が何であるかはわかりません。私のように怠け者であれば、私のgo.batはそのようなもののために働きます。 (下記参照)ただし、1、入力をコマンドとして直接使用している場合、OPのコマンドは無効になる可能性があります。すなわち

"C:/Users/Me"

無効なコマンドです(または別のドライブにいた場合に使用されていました)。あなたはそれを二つの部分に分ける必要があります。

C:
cd /Users/Me

そして、2、「定義済み」または「未定義」とはどういう意味ですか? GIGOデフォルトを使用してエラーを見つけます。入力がキャッチされない場合は、助けに(またはデフォルトのコマンド)にドロップします。したがって、入力がなくてもエラーにはなりません。入力にcdしてエラーがあればそれをキャッチすることができます。 (さて、 "go"ダウンロード(1つの親のみ)を使用することはDOSによって捕らえられます。

cd "%1"
if %errorlevel% neq 0 goto :error

そして、3、引用符はパスではなくコマンドではなく必要です。すなわち

"cd C:\Users" 

あなたが別のドライブにいない限り、悪かった(または昔は慣れていなかった)。

cd "\Users" 

機能的です。

cd "\Users\Dr Whos infinite storage space"

パスにスペースがある場合は機能します。

@REM go.bat
@REM The @ sigh prevents echo on the current command
@REM The echo on/off turns on/off the echo command. Turn on for debugging
@REM You can't see this.
@echo off
if "help" == "%1" goto :help

if "c" == "%1" C:
if "c" == "%1" goto :done

if "d" == "%1" D:
if "d" == "%1" goto :done

if "home"=="%1" %homedrive%
if "home"=="%1" cd %homepath%
if "home"=="%1" if %errorlevel% neq 0 goto :error
if "home"=="%1" goto :done

if "docs" == "%1" goto :docs

@REM goto :help
echo Default command
cd %1
if %errorlevel% neq 0 goto :error
goto :done

:help
echo "Type go and a code for a location/directory
echo For example
echo go D
echo will change disks (D:)
echo go home
echo will change directories to the users home directory (%homepath%)
echo go pictures
echo will change directories to %homepath%\pictures
echo Notes
echo @ sigh prevents echo on the current command
echo The echo on/off turns on/off the echo command. Turn on for debugging
echo Paths (only) with folder names with spaces need to be inclosed in         quotes (not the ommand)
goto :done

:docs
echo executing "%homedrive%%homepath%\Documents"
%homedrive%
cd "%homepath%\Documents"\test error\
if %errorlevel% neq 0 goto :error
goto :done

:error
echo Error: Input (%1 %2 %3 %4 %5 %6 %7 %8 %9) or command is invalid
echo go help for help
goto :done

:done
0
Xorange