Какой синтаксис проверит, определено ли имя переменной, содержащее пробелы? - PullRequest
6 голосов
/ 24 ноября 2011

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

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

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!

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

Я ищу ответ, который НЕ включает расширение переменной с использованием% AB% или! AB!

Ответы [ 4 ]

5 голосов
/ 24 ноября 2011

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

Очевидно, вы знаете, как проверить это с отложенным расширением, а также работает FOR-параметры.

@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.
Вы не можете ввести второй escape, например AAA^^^ BBB, так как он ищет только переменную с именем AAA^

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

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

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

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

Sample.

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
3 голосов
/ 14 января 2012

Мне тоже нравится такой вопрос! :)

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

0 голосов
/ 01 марта 2015

Я делаю это, определяя флаг как ИСТИНА, если это необходимо ...

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=
0 голосов
/ 14 января 2012

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

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
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...