windows - una - ¿Cuál es la forma correcta de probar si la variable está vacía en un archivo por lotes?
shell script verificar si existe archivo (15)
Script 1:
Entrada ("Quitar 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 NULO):
Ejecutar ("Quitar Quotes.cmd") sin ningún parámetro con la secuencia de comandos anterior 1
Salida (% 1 está en blanco, vacío o NULO):
Welcome!
Press any key to continue . . .
Nota: Si establece una variable dentro de una instrucción IF ( ) ELSE ( )
, no estará disponible para DEFINED hasta que salga de la instrucción "IF" (a menos que esté habilitada "Expansión de variable retrasada"; una vez habilitada, use un signo de exclamación " ! "en lugar del porcentaje"% "símbolo}.
Por ejemplo:
Script 2:
Entrada ("Quitar Quotes.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: También eliminará las comillas de dentro de la cadena.
Por ejemplo (usando el script 1 o 2): C: / Users / Test / Documents / Batch Files> "Quotes Quotes.cmd" "Esto es" un "Test"
Salida (Script 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 ("Quitar Quotes.cmd") sin ningún parámetro en la secuencia de comandos 2:
Salida:
Welcome!
Press any key to continue . . .
Necesito probar si una variable está configurada o no. He intentado varias técnicas, pero parecen fallar cuando %1
está rodeado por comillas, como el caso en que %1
es "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.
Según este sitio , estos son los tipos de sintaxis IF
soportados. Entonces, no veo una manera de hacerlo.
IF [NOT] ERRORLEVEL number command
IF [NOT] string1==string2 command
IF [NOT] EXIST filename command
Creé este pequeño script por lotes basado en las respuestas aquí, ya que hay muchos válidos. Siéntase libre de agregar a esto siempre y cuando siga 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
De IF / ?:
Si las extensiones de comando están habilitadas, SI cambia de la siguiente manera:
IF [/I] string1 compare-op string2 command IF CMDEXTVERSION number command IF DEFINED variable command
......
El condicional DEFINED funciona igual que EXISTS, excepto que toma un nombre de variable de entorno y devuelve true si se define la variable de entorno.
He tenido muchos problemas con 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.
Tal vez no funcione si tiene citas, tal vez 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 permiten un vacío conjunto de citas para pasar como ''definido'', y algunas más complicadas no le permitirán encadenar a else
después.
Aquí hay una solución con la que estoy contento, por favor avíseme si encuentra un caso en la esquina que no funcionará.
:ifSet
if "%~1"=="" (Exit /B 1) else (Exit /B 0)
Tener esa subrutina en tu script, o en su propio .bat
, debería funcionar.
Entonces, si quisieras escribir (en pseudo):
if (var)
then something
else somethingElse
Puedes escribir:
(Call :ifSet %var% && (
Echo something
)) || (
Echo something else
)
Funcionó para todas 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:
- ¿Quieres comprobar
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
? No hay problema:((Call ifSet.bat %var%) && Echo set) || (Echo not set)
((Call ifSet.bat %var%) && Echo set) || (Echo not set)
Ingresé con menos de un mes de antigüedad (a pesar de que se me preguntó hace 8 años) ... espero que ahora se haya movido más allá de los archivos por lotes. ;-) Solía hacer esto todo el tiempo. Aunque no estoy seguro de cuál es el objetivo final. Si es perezoso como yo, mi go.bat trabaja para cosas como esas. (Consulte a continuación) Pero, 1, el comando en el OP podría no ser válido si está usando directamente la entrada como un comando. es decir,
"C:/Users/Me"
es un comando no válido (o solía serlo si estuviera en un disco diferente). Necesitas dividirlo en dos partes.
C:
cd /Users/Me
Y, 2, ¿qué significa "definido" o "indefinido"? GIGO. Utilizo el valor predeterminado para detectar errores. Si la entrada no queda atrapada, se convierte en ayuda (o un comando predeterminado). Entonces, ninguna entrada no es un error. Puede intentar hacer un cd a la entrada y detectar el error si hay uno. (Ok, usando ir "descargas (solo una paren) es capturada por DOS. (Harsh!))
cd "%1"
if %errorlevel% neq 0 goto :error
Y, 3, las comillas son necesarias solo alrededor de la ruta, no del comando. es decir,
"cd C:/Users"
era malo (o estaba acostumbrado en los viejos tiempos) a menos que estuvieras en una unidad diferente.
cd "/Users"
es funcional.
cd "/Users/Dr Whos infinite storage space"
funciona si tienes espacios en tu camino.
@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
La cadena vacía es un par de double-quotes
/ ""
, solo podemos probar la longitud:
set ARG=%1
if not defined ARG goto nomore
set CHAR=%ARG:~2,1%
if defined CHAR goto goon
luego prueba 2 caracteres contra double-quotes
:
if ^%ARG:~1,1% == ^" if ^%ARG:~0,1% == ^" goto blank
::else
goto goon
Aquí hay un script por lotes con el que puedes jugar. Creo que atrapa correctamente la cadena vacía.
Esto es solo un ejemplo, solo necesita personalizar 2 (o 3?) Pasos anteriores de acuerdo a 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
Este resultado de la prueba de 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" " "< "">" (")(") "" :: ""-" " "( )"">/>" ""
Para resumir las cosas:
set str=%~1
if not defined str ( echo Empty string )
Este código arrojará "Cadena vacía" si% 1 es "" o "" o está vacío. Se agregó a la respuesta aceptada que actualmente es incorrecta.
Pruebo con el código a continuación y está 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
)
Puedes usar
if defined (variable) echo That''s defined!
if not defined (variable) echo Nope. Undefined.
Puedes usar:
IF "%~1" == "" GOTO MyLabel
para quitar el conjunto externo de comillas. En general, este es un método más confiable que usar corchetes porque funcionará incluso si la variable tiene espacios.
Una de las mejores semi soluciones es copiar %1
en una variable y luego utilizar la expansión retardada, 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 el ajuste de param1 funcionará en muchos casos, como
test.bat hello"this is"a"test
test.bat you^&me
Pero fallará con contenidos extraños como
test.bat "&"^&
Si desea que sea al 99% a prueba de balas, ¿podría leer Cómo recibir incluso los parámetros de línea de comando más extraños?
Usualmente uso esto:
IF "%1."=="." GOTO MyLabel
Si% 1 está vacío, el IF comparará "." a "." que evaluará a verdadero.
Utilice "comando de variable IF DEFINED" para probar la variable en el archivo por lotes.
Pero si desea probar los parámetros del lote, intente los siguientes códigos para evitar entradas complicadas (como "1 2" o ab ^> cd)
set tmp="%1"
if "%tmp:"=.%"==".." (
echo empty
) else (
echo not empty
)
Utilice corchetes en lugar de comillas:
IF [%1] == [] GOTO MyLabel
Los paréntesis son inseguros : solo use corchetes.
Utilizando ! 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