2011-11-24 9 views
6

Los nombres de variables de entorno definidos por el usuario de Windows pueden contener cualquier carácter excepto =.¿Qué sintaxis verificará si se define un nombre de variable que contenga espacios?

Se pueden incluir caracteres especiales escapándolos. Un método más simple es simplemente encerrar toda la expresión SET entre comillas. Por ejemplo:

set "A weird & "complex" variable=My value" 
set A weird ^& "complex" variable=My value 

Ambas expresiones anteriores dan el mismo resultado. El nombre de la variable es A weird & "complex" variable y el valor es My value

El IF constructo definido se utiliza para probar si se define una variable. Las citas no funcionan para esta prueba, los caracteres especiales en el nombre (incluidas las comillas) se deben escapar.

set "A&B=value" 
if defined A^&B echo This works 
if defined "A&B" echo This does not work 

La prueba anterior escapada funciona bien. La prueba entrecomillada no funciona

Pero, ¿cómo puedo comprobar si existe una variable que contenga espacios?

set "A B=value" 
if defined A^ B echo this does not work! 

Parece que lo anterior debería funcionar, pero no es así.

Estoy buscando una respuesta que NO implique expandir la variable usando% A B% o! A B!

Respuesta

5

Pregunta de interés (me encantan estas preguntas de base de sintaxis).

Obviamente, usted sabe cómo verificarlo con la expansión retardada y también funciona con FOR-parameters.

@echo off 
setlocal 
set "AAA BBB=value" 
set ""AAA BBB"=" 
set "AAA=" 
for %%a in ("AAA BBB") do if defined %%~a echo FOR: This works 

setlocal EnableDelayedExpansion 
set "varname=AAA BBB" 
if defined !varname! echo Delayed: This works 

if defined %varname% (echo percent: Never comes here 
) ELSE (echo percent: Never comes here ?) 

if defined AAA^ BBB (echo escape1: Never comes here 
) ELSE (echo escape1: fails) 

set AAA=Hello 
if defined AAA^ BBB ( 
    echo escape2: It only test for AAA the BBB will be "removed" 
) ELSE (echo escape2: fails) 

set "space= " 
if defined AAA!space!BBB echo inject space: This works 

if defined "AAA BBB" (echo Quote1: Never comes here 
) ELSE (echo Quote1: Fails) 

set ""AAA BBB"=value" 
if defined "AAA BBB" echo Quote2: This works, it checks for "AAA BBB" with quotes 

En mi opionion, en el ejemplo escape2 el analizador primero divide la línea en tokens de esta forma:
<if> <defined> <AAA BBB> <echo .... Pero en el tiempo de ejecución del si está definido se repite el análisis de la señal de <AAA BBB> por lo que solo obtiene el AAA.
No se puede inyectar un medio secundario como AAA^^^ BBB ya que esto sólo busca la variable llamada AAA^

no puedo ver una solución sin que se retrase/DE, como el escape del espacio siempre falla.

EDIT: También se puede resolver con SET <varname>
La solución de ijprest utiliza el comando SET para probar la variable sin la necesidad de escapar de la nombre_var.
Pero también muestra un comportamiento interesante con espacios dentro y al final de un varname.

Parece que seguir estas reglas:
SET varname búsquedas para todas las variables que comienzan con nombre_var, pero primero que elimina todos los caracteres después del último carácter de espacio de nombre_var, y elimina todos los espacios iniciales.
Por lo tanto, no puede buscar variables que comiencen con espacio (pero también es un poco complicado crear dicho nombre var).

El mismo comportamiento también está activo si el nombre de variable está entre comillas, pero existe una regla más.
Primero elimine todos los caracteres después de la última cita, si hay al menos dos comillas. Usa el texto dentro de las comillas y usa la regla "espacio".

Muestra.

set " abc def ghi" junk junk 
*** 1. removes the junk 
set " abc def ghi" 
*** 2. removes the quotes 
set  abc def ghi 
*** 3. removes all after the last space, and the trailing spaces 
set abc def 
*** Search all variables beginning with abc def 
+0

El DE /! Retrasar! La solución no era obvia cuando necesitaba dormir. ¡Pensé en eso cuando me desperté, pero ya tienes una excelente respuesta publicada! :) – dbenham

+0

Su análisis * escape2 * es muy interesante. Otra oportunidad para insertar un comentario en una declaración – dbenham

0

La otra manera es volver a asignar a otra variable (uno sin espacios) y la prueba de que . Vea aquí:

rem Prepare ONLY variable 'a b' 
set "a b=123" 
echo [a b]=%a b% 

rem This will ouput: [a b] is defined 
set var=%a b% 
if defined var (
    echo [a b] is defined 
) else (
    echo [a b] is not defined 
) 

rem This will output: [c d] is not defined 
set var=%c d% 
if defined var (
    echo [c d] is defined 
) else (
    echo [c d] is not defined 
) 
+0

Por supuesto que funciona, pero el último requisito de mi pregunta original indicaba que estaba buscando una respuesta que NO utilizara% A B% o! A B !. (Por cierto, asignar! A B! Es mucho más seguro. La asignación de% A B% puede fallar dependiendo de los contenidos) – dbenham

3

¡También me gusta este tipo de pregunta! :)

Aquí es otra posible solución que se me ocurrió ... usando SET sí para probar la existencia, y usando el resultado ERRORLEVEL:

set "A B=foo" 
set A B >nul 2>nul&& echo 1. This works 
set "A B ">nul 2>nul&& echo 2. This works 

set "A weird & "complex" variable=foo" 
set A weird ^& "complex" variable >nul 2>nul&& echo 3. This works 
set "A weird & "complex" variable ">nul 2>nul&& echo 4. This works 

Tenga en cuenta que esto sólo funciona si las variables son única en el sentido de que ningún nombre de variable es el prefijo de otro. De lo contrario, corre el riesgo de falsos positivos, ya que el comportamiento predeterminado de SET es mostrar todas las variables que comienzan con el parámetro que pasa. Si esto podría ser el caso, se podría filtrar los resultados con findstr:

set "A B=" 
set "A B C=foo" 
set "A B ">nul 2>nul&& echo 5. Failed (false positive) 
set "A B "|findstr /B /L /C:"A B=" >nul||echo 6. This works (no false positive) 

Además, el espacio sola final después del nombre de la variable parece ser necesario. Sin esto, SET a menudo malinterpreta la entrada. Curiosamente, si agrega un espacio extra entre "2> nul" y "& &" en el caso n. ° 3 deja de funcionar (a menos que elimine el espacio antes de "> nul") ... raro.

+0

+1 Buena solución con la adición de FINDSTR. Había pensado en la prueba SET y la rechacé, pero no pensé en agregar FINDSTR. Todavía prefiero la solución de jeb porque no requiere tubería ni comando externo, por lo que es más rápido. – dbenham

+0

Descubrimiento muy interesante sobre el espacio extra requerido, de lo contrario, cualquier variable que comience con coincidencias "a". Las citas no son necesarias. 'establecer b' falla. 'establecer un b ' funciona. 'establecer un b ' ¡falla! @jeb - ¿Alguna idea de lo que está pasando aquí? – dbenham

+0

Agregué un comentario a mi [respuesta] (http://stackoverflow.com/a/8257295/463115) sobre el comportamiento del espacio SET – jeb

-2

lo hago mediante la definición de una bandera como TRUE si es necesario ...

rem /* sample code */ 
set VAR_SET= 
if <some condition> set VAR_SET=TRUE&set VAR=this data has spaces 

rem /* test for VAR_SET using 'if defined' */ 
if defined VAR_SET (
    rem /* do something with the other data in the variable %VAR% */ 
) 

rem /* clear the flag */ 
set VAR_SET= 
+1

No ha respondido la pregunta: ha olvidado completamente el punto. – dbenham

Cuestiones relacionadas