IT

배치 파일에서 매개 변수가 비어 있는지 테스트하는 올바른 방법은 무엇입니까?

lottoking 2020. 5. 12. 08:26
반응형

배치 파일에서 매개 변수가 비어 있는지 테스트하는 올바른 방법은 무엇입니까?


변수가 설정되어 있는지 테스트해야합니다. 나는 몇 가지 기술을 시도했지만 그들은 때마다 실패하는 것 %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

따옴표 대신 대괄호를 사용하십시오.

IF [%1] == [] GOTO MyLabel

괄호는 안전하지 않습니다 . 대괄호 만 사용하십시오.


당신이 사용할 수있는:

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

외부 따옴표 세트를 제거합니다. 일반적으로 대괄호를 사용하는 것보다 변수가 공백이 있어도 작동하기 때문에이 방법이 더 안정적입니다.


가장 좋은 반 솔루션 중 하나는 %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 %의 방탄을 원한다면 가장 이상한 명령 줄 매개 변수를받는 방법도 읽을 수 있습니다 .


IF /?에서 :

명령 확장이 활성화 된 경우 IF는 다음과 같이 변경됩니다.

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

......

DEFINED 조건은 환경 변수 이름을 사용하고 환경 변수가 정의 된 경우 true를 리턴한다는 점을 제외하고 EXISTS와 동일하게 작동합니다.


배치 파일에서 변수를 테스트하려면 "IF DEFINED 변수 명령"을 사용하십시오.

그러나 배치 매개 변수를 테스트하려면 까다로운 입력을 피하기 위해 아래 코드를 시도하십시오 (예 : "1 2"또는 ab ^> cd)

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

불행히도 나는 내 자신의 글을 써야했던 현재의 답변에 대해 의견을 표하거나 투표 할만한 명성을 얻지 못했습니다.

원래 OP의 질문은 "매개 변수"가 아닌 "변수"라고 말했는데, 이는 매우 혼란 스러웠습니다. 특히 빈 변수를 테스트하는 방법을 검색하는 Google의 가장 큰 링크였습니다. 내 원래 답변 이후 Stephan은 올바른 용어를 사용하도록 원래 질문을 편집했지만 내 답변을 삭제하지 않고 혼란을 없애기 위해 남겨두기로 결정했습니다. 특히 Google이 여전히 사람들에게 변수를 보내려고하는 경우에는 특히 그렇습니다.

% 1은 (는) 가치가 없습니다! 명령 줄 매개 변수입니다.

매우 중요한 차이점. 변수가 아닌 명령 행 매개 변수를 참조한 후 숫자가있는 단일 퍼센트 부호.

변수는 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의 답변을 참조하는 것이 좋습니다.)


아래 코드로 테스트하면 괜찮습니다.

@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
)

나는 보통 이것을 사용합니다 :

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

% 1이 비어 있으면 IF는 "."을 비교합니다. "." 이것은 참으로 평가됩니다.


유효한 스크립트가 많으므로 여기에 대한 답변을 기반 으로이 작은 배치 스크립트를 만들었습니다. 동일한 형식을 따르는 한 자유롭게 추가하십시오.

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

빈 문자열은 double-quotes/ 쌍이며 ""길이를 테스트 할 수 있습니다.

set ARG=%1
if not defined ARG goto nomore

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

그런 다음 2 문자인지 테스트하십시오 double-quotes.

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" " "< "">"  (")(") "" :: ""-"  " "( )"">\>" ""


당신이 사용할 수있는

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

스크립트 1 :

입력 ( "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 임) :


위의 스크립트로 매개 변수없이 ( "Quotes.cmd 제거")를 실행 1

출력 (% 1이 비어 있거나 비어 있거나 NULL 임) :

Welcome!

Press any key to continue . . .

참고 : IF ( ) ELSE ( )명령문 내에 변수를 설정 한 경우 "IF"문을 종료 할 때까지 DEFINED에서 사용할 수 없습니다 ( "지연된 변수 확장"이 활성화되어 있지 않으면 활성화 된 경우 "!"대신 느낌표 "!"사용) 퍼센트 "%"기호}.

예를 들면 다음과 같습니다.

스크립트 2 :

입력 ( "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> "Quotes.cmd 제거" ""a "테스트"

출력 (스크립트 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의 매개 변수없이 ( "Quotes.cmd 제거")를 실행하십시오.

산출:

Welcome!

Press any key to continue . . .

요약하면 다음과 같습니다.

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

This code will output "Empty string" if %1 is either "" or " or empty. Added it to the accepted answer that's currently incorrect.


I've had a lot of issues with a lot of answers on the net. Most work for most things, but there's always a corner case that breaks each one.
Maybe it doesn't work if it's got quotes, maybe it breaks if it doesn't have quotes, syntax error if the var has a space, some will only work on parameters (as opposed to environment variables), other techniques allow an empty set of quotes to pass as 'defined', and some trickier ones won't let you chain an else afterward.

Here's a solution I'm happy with, please let me know if you find a corner case it won't work for.

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

Having that subroutine either in a your script, or in it's own .bat, should work.
So if you wanted to write (in pseudo):

if (var)
then something
else somethingElse

You can write:

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

It worked for all my tests:

(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

Echo'd n, y, n, y, y


More examples:

  • Wanna just check if? Call :ifSet %var% && Echo set
  • Just if not (only the else)? Call :ifSet %var% || Echo set
  • Checking a passed argument; works fine. Call :ifSet %1 && Echo set
  • Didn't want to clog up your scripts/dupe code, so you put it in it's own ifSet.bat? No problem: ((Call ifSet.bat %var%) && Echo set) || (Echo not set)

Using ! instead of " for empty string checking

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

I got in in just under a month old (even though it was asked 8 years ago)... I hope s/he's moved beyond batch files by now. ;-) I used to do this all the time. I'm not sure what the ultimate goal is, though. If s/he's lazy like me, my go.bat works for stuff like that. (See below) But, 1, the command in the OP could be invalid if you are directly using the input as a command. i.e.,

"C:/Users/Me"

is an invalid command (or used to be if you were on a different drive). You need to break it in two parts.

C:
cd /Users/Me

And, 2, what does 'defined' or 'undefined' mean? GIGO. I use the default to catch errors. If the input doesn't get caught, it drops to help (or a default command). So, no input is not an error. You can try to cd to the input and catch the error if there is one. (Ok, using go "downloads (only one paren) is caught by DOS. (Harsh!))

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

And, 3, quotes are needed only around the path, not the command. i.e.,

"cd C:\Users" 

was bad (or used to in the old days) unless you were on a different drive.

cd "\Users" 

is functional.

cd "\Users\Dr Whos infinite storage space"

works if you have spaces in your path.

@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

참고URL : https://stackoverflow.com/questions/2541767/what-is-the-proper-way-to-test-if-a-parameter-is-empty-in-a-batch-file

반응형