Какой синтаксис будет проверять, определено ли имя переменной, содержащее пробелы?

имена пользовательских переменных среды Windows могут содержать любой символ, кроме =.

специальные символы могут быть включены, избегая их. Более простой метод - просто заключить все выражение набора в кавычки. Например:

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

оба выражения дают одинаковый результат. Имя переменной A weird & "complex" variable и значение My value

конструкция IF DEFINED используется для проверки переменная определена. Цитаты не работают для этого теста, специальные символы в имени (включая кавычки), должны быть экранированы.

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

вышеприведенный экранированный тест работает просто отлично. Цитируемый тест не работает

но как я могу проверить, существует ли переменная, содержащая пробелы?

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

кажется, что выше должно работать, но это не так!

Я ищу ответ, который не включает в себя расширение переменной с помощью %A B% или !Б!

4 ответов


интересный вопрос (мне нравится этот синтаксис базовых вопросов).

очевидно, вы знаете, как проверить его с задержкой расширения, а также для-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

у меня такое, в escape2 пример парсер сначала разделил строку на токены таким образом:
<if> <defined> <AAA BBB> <echo .... Но во время исполнения если определено это пересканировать <AAA BBB> токен, поэтому он получает только AAA.
Ты не можешь сделать второй побег. как AAA^^^ BBB как это только ищет переменную с именем AAA^

Я не вижу решения без задержки/для, так как выход из пространства всегда терпит неудачу.

EDIT: его также можно решить с помощью SET <varname>
Решение ijprest использует команду SET для тестирования переменной без необходимости экранирования varname.
Но он также показывает интересное поведение с пробелами внутри и в конце varname.

кажется следуйте этим правилам:
SET varname ищет все переменные, начинающиеся с varname, но сначала удаляет все символы после последнего символа пробела varname, и удаляет все ведущие пробелы.
Таким образом, вы не можете искать переменные, начинающиеся с пространства (но также немного сложно создать такое имя varname).

то же самое поведение также активно, если переменное имя заключено в кавычки, но затем существует еще одно правило.
Сначала удалите все символы после последней цитаты, Если есть хотя бы две цитаты. Используйте текст внутри кавычек и используйте"пробел" -правило.

образец.

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

Я тоже люблю такого рода вопрос! :)

вот еще одно возможное решение, которое я придумал... использование SET для проверки существования и использование результата 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

обратите внимание, что это работает, только если ваши переменные уникальный в том смысле, что ни одно имя переменной не является префиксом другого. В противном случае вы рискуете ложными срабатываниями, так как поведение SET по умолчанию-показать все переменные, начинающиеся с передаваемого параметра. Если бы это было возможно ... в случае, вы можете отфильтровать результаты с помощью 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)

и один конечное пространство после имени переменной, по-видимому, требуется. Без него SET часто неправильно анализирует входные данные. Странно, если вы добавляете дополнительное пространство между "2>nul" и " & & "в случае #3 он перестает работать (если вы не удалите пространство перед ">nul")... странный.


другой способ-переназначить его на другую переменную (без пробелов) и проверить это. Смотрите здесь:

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
)

Я делаю это, определяя флаг как TRUE, если это необходимо...

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=