Эхо точная строка в пакетном файле Windows? - PullRequest
5 голосов
/ 18 марта 2012

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

setlocal EnableDelayedExpansion
@echo off
set "grass=@##&!$^&%**(&)"
echo !grass!

Я хочу вывести переменную grass дословно, чтобы я увидел @##&!$^&%**(&) в выводе. Что нужно сделать? Спасибо!

Ответы [ 2 ]

13 голосов
/ 18 марта 2012

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

Правильная escape-последовательность для установки значения:

set "grass=@##&^!$^^&%%**(&)"

А теперь объяснение. Необходимая информация находится в Как синтаксический анализ сценариев интерпретатора команд Windows (CMD.EXE)? . Но это немного трудно следовать.

У вас есть две проблемы:

1) % необходимо экранировать как %% для каждого анализа строки. Наличие или отсутствие цитат не имеет значения. Состояние отложенного расширения также не имеет значения.

 set pct=%
 :: pct is undefined

 set pct=%%
 :: pct=%

 call set pct=%%
 :: pct is undefined because the line is parsed twice due to CALL

 call set pct=%%%%
 :: pct=%

2) Литерал ! должен быть экранирован как ^! всякий раз, когда он анализируется фазой отложенного расширения анализатора. Если строка содержит ! где-либо внутри нее во время отложенного расширения, то литерал ^ должен быть экранирован как ^^. Но ^ также должен быть заключен в кавычки или экранирован как ^^ для фазы специальных символов синтаксического анализатора. Это может быть еще более осложнено тем фактом, что CALL удвоит любые ^ символов. (Извините, описать проблему очень сложно, а синтаксический анализатор сложен!)

setlocal disableDelayedExpansion

set test=^^
:: test=^

set "test=^"
:: test=^

call set test=^^
:: test=^
:: 1st pass - ^^ becomes ^
:: CALL doubles ^, so we are back to ^^
:: 2nd pass - ^^ becomes ^

call set "test=^"
:: test=^^ because of CALL doubling. There is nothing that can prevent this.

set "test=^...!"
:: test=^...!
:: ! has no impact on ^ when delayed expansion is disabled

setlocal enableDelayedExpansion

set "test=^"
:: test=^
:: There is no ! on the line, so no need to escape the quoted ^.

set "test=^!"
:: test=!

set test=^^!
:: test=!
:: ! must be escaped, and then the unquoted escape must be escaped

set var=hello
set "test=!var! ^^ ^!"
:: test=hello ^ !
:: quoted ^ literal must be escaped because ! appears in line

set test=!var! ^^^^ ^^!
:: test=hello ^ !
:: The unquoted escape for the ^ literal must itself be escaped
:: The same is true for the ! literal

call set test=!var! ^^^^ ^^!
:: test=hello ^ !
:: Delayed expansion phase occurs in the 1st pass only
:: CALL doubling protects the unquoted ^ literal in the 2nd pass

call set "test=!var! ^^ ^!"
:: test=hello ^^ !
:: Again, there is no way to prevent the doubling of the quoted ^ literal
:: when it is passed through CALL
2 голосов
/ 18 марта 2012

Как сказал Дбенхем, это всего лишь задание.
Вы можете использовать экранирование, как показано в dbenham, это необходимо, поскольку EnableDelayedExpansion активен, пока вы устанавливаете значение.
Поэтому вам нужно избегать восклицательного знака, а символ вставки должен быть экранирован, поскольку в строке есть один восклицательный знак, кавычки в этой ситуации бесполезны.
Но вы также можете установить значение до , когда вы активируете EnableDelayedExpansion,
Тогда вам не нужны были ласки.

...