2010-03-29 6 views
144

Necesito comprobar si una variable está configurada o no. He intentado varias técnicas, pero parecen fallar cada vez que %1 está rodeado por comillas, como el caso en que %1 es "c:\some path with spaces".¿Cuál es la forma correcta de probar si la variable está vacía en un archivo por lotes?

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. 

Según this site, estos son los tipos IF sintaxis soportada. Entonces, no veo una manera de hacerlo.

IF [NOT] ERRORLEVEL number command 
IF [NOT] string1==string2 command 
IF [NOT] EXIST filename command 
+1

En mis sistemas (Windows 2003, así como Windows 7), 'si "1%" == "" GOTO MyLabel' no mata fatalmente la ejecución del script, siempre y cuando'% 1' tiene un número par de comillas dobles. Veo que un número impar de comillas dobles en '% 1' mata la ejecución del script con este error:' La sintaxis del comando es incorrecta. La solución a continuación que usa corchetes para resolver el problema se ha marcado como la respuesta correcta, pero no parece estar mejorando. Esa solución también falla con el mismo error cuando '% 1' tiene un número impar de comillas dobles. –

+0

@SusamPal Interesante. Pruebe la versión de paréntesis debajo de él y vea si eso funciona. Ese que probé más. Acabo de actualizar la respuesta aceptada hace un par de días. – blak3r

+0

[La respuesta de Dan Story] (http://stackoverflow.com/a/2541820/303363) parece funcionar bien. Usé la versión usando corchetes. –

Respuesta

206

Use corchetes en lugar de comillas:

IF [%1] == [] GOTO MyLabel 

paréntesis son inseguros : sólo utilizan corchetes.

+8

paréntesis no son seguros! El contenido como '&' en '% 1' romperá la línea – jeb

+8

Usando otros caracteres como' if #% 1 # == ## 'o' if [% 1] == [] 'es bueno siempre que no haya espacios en el argumento, de lo contrario recibirá un error '... inesperado en este momento'. – Synetech

+13

Esto no funciona si el texto variable tiene espacios dentro de él. – kungfujam

1

que suelen utilizar esto:

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

Si% 1 está vacía, el SI comparará "" a "." que evaluará a verdadero.

+4

Esto es lo mismo que: SI "% 1" == "" el motivo de esta publicación fue si% 1 tiene presupuestos que fallan. – blak3r

+0

¿Está intentando probar si% 1 está vacío? o si tiene comillas? La pregunta no está clara. Mi respuesta funciona si no se especifica nada en la línea de comando para% 1. – aphoria

+0

*> ¿Está tratando de probar si% 1 está vacío o si tiene comillas? * @ Aphoria, tiene que ser capaz de manejar ambos. – Synetech

89

Se puede utilizar:

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

para despojar el conjunto exterior de cotizaciones. En general, este es un método más confiable que usar corchetes porque funcionará incluso si la variable tiene espacios.

+1

+1 No lo he intentado. Pero, eso es genial saberlo. – blak3r

+7

Esta es de hecho una buena manera de hacerlo. Al usar '~', tiras las comillas externas si están presentes, pero luego las vuelves a agregar manualmente (lo que garantiza un solo conjunto). Además, * tienes * que usar comillas si el argumento contiene espacios (lo aprendí de la manera difícil cuando mi versión anterior de usar '#' o corchetes en lugar de comillas causaba argumentos con espacios para arrojar un '... inesperado en este momento' error). – Synetech

+1

¿Esto también es aplicable para variables generales como% MYVAR% en lugar de los argumentos como% 1? – simpleuser

12

De IF/?:

If Command Extensions are enabled IF changes as follows:

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

......

The DEFINED conditional works just like EXISTS except it takes an environment variable name and returns true if the environment variable is defined.

+0

Sí, de hecho probé este enfoque y por lo que pude ver, esto solo funciona con variables ENTORNO. Por lo tanto, no funcionó con% 1 o una variable definido dentro del archivo por lotes. – blak3r

+1

Eso solo es cierto para '% 1' y los me gusta."Las variables definidas dentro del archivo por lotes" en realidad ** son ** variables de entorno mientras se está ejecutando el archivo por lotes, y puede usar 'IF DEFINED' en ellas. – zb226

1

Guión 1:

de entrada ("Eliminar Quotes.cmd" "Esto es una prueba")

@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 

salida (No hay ninguno ,% 1 no estaba en blanco, vacío, o NULL):


Run ("Eliminar Quotes.cmd") sin ningún parámetro con el guión anterior 1

de salida (1% está en blanco, vacío, o NULL):

Welcome! 

Press any key to continue . . . 

Nota: Si configura una variable dentro de una declaración IF () ELSE (), no estará disponible para DEFINIDO hasta que salga de la instrucción "IF" (a menos que esté habilitada la "Expansión de la variable retrasada"; una vez habilitado use un signo de exclamación "!" en lugar del porcentaje "%" símbolo}.

Por ejemplo:

Guión 2:

de entrada ("Eliminar Cotizaciones.cmd" "Esto es una prueba")

@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 

Salida:

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> 

Nota:. Además, eliminará las cotizaciones desde el interior de la cadena

por ejemplo (usando la escritura 1 o 2): C: \ Users \ Test \ Documents \ Batch Files> "Remove Quotes.cmd" "Esto es" a "Test"

Outp UT (Guión 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 

Ejecutar ("Eliminar Quotes.cmd") sin ningún parámetro en Script 2:

Salida:

Welcome! 

Press any key to continue . . . 
26

Uno de los mejores semi solutions es copiar %1 en una variable y luego usar la expansión retrasada, como delayyedExp. siempre es seguro contra cualquier contenido.

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 

La ventaja de esto es que lidiar con param1 es absolutamente seguro.

y la fijación de param1 trabajará en muchos casos, como

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

Pero va a fallar con contenidos extraños como

test.bat "&"^& 

Si quieres ser el 99% a prueba de balas que se podía leer How to receive even the strangest command line parameters?

3

Utilice "comando variable IF DEFINED" para probar la variable en el archivo por lotes.

Pero si desea probar los parámetros de proceso por lotes, tratar a continuación los códigos de entrada para evitar complicado (como "1 2" o ab ^> cd)

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

que he tenido un montón de problemas con una muchas respuestas en la red. La mayoría trabaja para la mayoría de las cosas, pero siempre hay un caso de esquina que las rompe.
Quizás no funcione si tiene comillas, quizás se rompa si no tiene comillas, error de sintaxis si la var tiene un espacio, algunas solo trabajarán en parámetros (a diferencia de las variables de entorno), otras técnicas lo permiten un conjunto vacío de citas para pasar como 'definido', y algunas más complicadas no le permitirán encadenar un else después.

Aquí hay una solución con la que estoy contento, por favor avíseme si encuentra un caso de esquina que no funcionará.

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

Tener esa subrutina ya sea en una secuencia de comandos, o en su propio .bat, debería funcionar.
Así que si quería escribir (pseudo):

if (var) 
then something 
else somethingElse 

Se puede escribir:

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

funcionó para todos mis pruebas:

(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


Más ejemplos:

  • Wanna sólo echa if? Call :ifSet %var% && Echo set
  • ¿Solo si no (solo el otro)? Call :ifSet %var% || Echo set
  • Comprobando un argumento pasado; funciona bien. Call :ifSet %1 && Echo set
  • ¿No quería obstruir sus scripts/código de engaño, por lo que lo puso en su propio ifSet.bat? Ningún problema: ((Call ifSet.bat %var%) && Echo set) || (Echo not set)
+0

Encontrado un caso; Si prueba la sintaxis if with else, y el último comando del bloque then falla, el else ejecutará: '(Call ifSet.bat YES && (Echo true & Echo x | findstr y)) || Echo', echos 'true' * y *' false' – Hashbrown

+0

En realidad, si esto es un problema, y ​​puede tratar con una línea adicional, puede mitigar esto llamando a 'ifSet' por sí mismo, y luego usando' If% errorlevel % EQU 0 (x) Else (y) ' – Hashbrown

+0

¿En qué casos no funciona la respuesta aceptada (use corchetes)? ¿Y puede explicar lo que Exit/B hace – blak3r

1

Creé este pequeño script por lotes basado en las respuestas aquí, ya que hay muchos válidos. No dude en añadir a esta, siempre y cuando usted sigue el mismo formato:

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

Cadena vacía es un par de double-quotes/"", sólo podemos probar la longitud:

set ARG=%1 
if not defined ARG goto nomore 

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

entonces probar que es 2 personajes contra double-quotes:

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

Aquí hay una escritura de la hornada se puede jugar con. Creo que atrapa correctamente la cadena vacía.

Esto es solo un ejemplo, solo necesita personalizar 2 (o 3?) Pasos anteriores de acuerdo con su secuencia de comandos.

@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 

resultado de esta prueba la tortura:

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

Está mal , una cadena vacía no es una cadena con dos comillas dobles '" "' una cadena vacía es una cadena vacía '' y en lote una variable vacía es una variable indefinida. Puede definir que, para sus argumentos, se eliminarán las comillas externas, pero la cadena todavía está vacía con una longitud de 0 – jeb

+0

En este contexto (argumentos win cmd), no se puede denotar una cadena vacía de ninguna otra manera, no incluso con doble comilla simple que igualmente vacía bajo el shell de Unix. – user6801759

+0

Sí, '" "' también se usan para cadenas vacías, pero es bastante fácil usar '% ~ 1' para eliminar las comillas externas. no hay necesidad de utilizar una solución tan compleja – jeb

1

Para acabar:

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

Este código es la salida "Cadena vacía" si% 1 es "" o "o vacíos Se lo agregó a la respuesta aceptada que actualmente es incorrecta.

0

Usando! En lugar de "para comprobación de cadena vacía

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

La sugerencia es realmente mala. Las citas pueden manejar espacios y caracteres especiales al menos, pero las exclamaciones no pueden. Y los signos de exclamación se ponen realmente desagradables aquí cuando se habilita la expansión retrasada – jeb

0

Puede utilizar

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

¡Bienvenido a SO! Su respuesta parece una buena respuesta a la pregunta. Una vez que tenga suficiente [reputación] (http://stackoverflow.com/help/whats-reputation) podrá [comentar] (http://stackoverflow.com/help/privileges/comment) en cualquier publicación. También puedes ver este [¿qué puedo hacer yo en su lugar] (https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead) – thewaywewere

0

pongo a prueba con el código de abajo y es bien.

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

Su solución falla cuando la variable contiene una cita. Por cierto, existe la sintaxis 'IF DEFINED var' por una razón – jeb

Cuestiones relacionadas