Как избежать переменных с круглыми скобками внутри if-clause в пакетном файле?

Запуск этого командного файла

@echo off
set a=some value with (parentheses) inside
if 1 == 1 (
    set PATH=%a%
)

дает ошибку inside was unexpected at this time..

Как избежать переменной a, чтобы избежать этой ошибки?

Ответ 1

Вы можете использовать два разных способа.

Использовать расширенный синтаксис set с кавычками set "var=content" будет устанавливать var с содержимым, контент цитируется, поэтому специальные символы не являются проблематичными, и он использует контент до последней цитаты (без самой цитаты).

@echo off
set a=some value with (parentheses) inside
if 1 == 1 (
    set "PATH=%a%"
)

Используйте задержанное расширение (например, ответ shf301), но также передайте значение в основной объем.

@echo off
setlocal enabledelayedexpansion
set a=some value with (parentheses) inside
if 1 == 1 (
    set "localScope_PATH=!a!"
    rem now transfer it to the global scope
    FOR /F "delims=" %%A in ("!localScope_PATH!") DO (
       endlocal
       set "path=%%A"
    )
)

В этом случае расширенный синтаксис не нужен, я использовал его только для того, чтобы избежать скрытых пространств в конце строки.

EDIT: Могу ли я объединить это с setlocal EnableDelayedExpansion и использовать! вместо% lazy оценить значение переменной? Когда я попробовал, я получил)! было неожиданным в настоящее время.

Вы можете, но это непротиворечиво, поскольку

@echo off
Setlocal EnableDelayedExpansion
set a=some value with (parentheses) inside
if 1 == 1 (
    set PATH=!a:^)=^^^)!
    set path
)

Затем ваш путь содержит каретки перед ) как C:\programs (x86^)

Чтобы понять, как работает расширение, вы можете прочитать SO: Как интерпретатор сценариев Windows Command Interpreter (CMD.EXE)?

EDIT2: больше проблем с контуром (содержащие кавычки)
В соответствии с этим question может возникнуть другая проблема с круглыми скобками, когда путь содержит кавычки.

Пример
path="C:\Program Files (x86)";C:\Program Files (x86)\Skype

Это разрешено, даже не обязательно использовать кавычки здесь, но это разрушает расширенный синтаксис set, так как теперь set "newPath=%path%" расширяется до

set "newPath="C:\Program Files (x86)";C:\Program Files (x86)\Skype"

Теперь, по крайней мере, одна скобка не находится внутри кавычек и может сломать командный блок.

Но вы можете просто удалить все кавычки из переменной пути, как сказано, цитаты здесь не нужны.

set "newPath=%path:"=%"

Ответ 2

Проблема ) in %a% - проблема здесь. Вы можете просто выполнить некоторую замену, чтобы избежать ).

@echo off
set a=some value with (parentheses) inside
if 1 == 1 (
    set PATH=%a:)=^)%
)

Ответ 3

Использование задержанного расширения исправит это:

@echo off
setlocal enabledelayedexpansion
set a=some value with (parentheses) inside
if 1 == 1 (
    set PATH=!a!
)

Без замедленного расширения блок if (от if до конца ),% a% заменяется первым, а затем блок анализируется и запускается. С задержкой расширения! a! не расширяется после блока анализируется, поэтому логика синтаксического анализа не увидит) в a и не вызовет проблем.

Ответ 4

Скобки и переменные всегда больно смешивать. Вместо этого используйте подпрограмму.

@Echo Off
Set a=some value with (parentheses) inside
If 1 == 1 Call :SetPath
Echo %Path%
Exit /B

:SetPath
Set "Path=%a%"
SetX "Path" "%a%"
Exit /B

Я устанавливаю переменную дважды, используя Set для текущего сеанса оболочки, а другой - SetX, чтобы установить его в системном для будущих сеансов оболочки. Удалите либо, если они не нужны.