Есть методы, позволяющие избежать ^
escape-последовательностей.
Вы можете использовать переменные с отложенным расширением. Ниже представлена небольшая демонстрация пакетного сценария.
@echo off
setlocal enableDelayedExpansion
set "line=<html>"
echo !line!
Или вы можете использовать цикл FOR / F. Из командной строки:
for /f "delims=" %A in ("<html>") do @echo %~A
Или из пакетного скрипта:
@echo off
for /f "delims=" %%A in ("<html>") do echo %%~A
Причина этих методы работа , потому что оба отсроченное расширение и для расширения переменного происходит после специальных операторов , такие как <
, >
, &
, |
, &&
, ||
обрабатывается. См. Как интерпретатор команд Windows (CMD.EXE) анализирует сценарии? для получения дополнительной информации.
sin3.14 указывает, что для каналов может потребоваться несколько экранирований . Например:
echo ^^^<html^^^>|findstr .
Причина, по которой для каналов требуется несколько экранирований, заключается в том, что каждая сторона канала выполняется в новом процессе CMD, поэтому строка анализируется несколько раз. См. Почему не удается отложенное расширение внутри блока кода, передаваемого по конвейеру? для объяснения многих неудобных последствий реализации канала Window.
Есть еще один способ избежать многократных выходов при использовании каналов. Вы можете явно создать экземпляр своего собственного процесса CMD и защитить одиночный escape-код кавычками:
cmd /c "echo ^<html^>"|findstr .
Если вы хотите использовать технику отложенного расширения, чтобы избежать побега, тогда есть еще больше сюрпризов (вы можете не удивиться, если вы эксперт по дизайну CMD.EXE, но нет официальной документации MicroSoft, объясняющей этот материал)
Помните, что каждая сторона конвейера выполняется в своем собственном процессе CMD.EXE, но процесс не наследует состояние отложенного раскрытия - по умолчанию оно выключено. Таким образом, вы должны явно создать экземпляр своего собственного процесса CMD.EXE и использовать параметр / V: ON, чтобы включить отложенное расширение.
@echo off
setlocal disableDelayedExpansion
set "line=<html>"
cmd /v:on /c echo !test!|findstr .
Обратите внимание, что отложенное расширение отключено в родительском пакетном сценарии.
Но ад вырвется наружу, если в родительском скрипте включено отложенное расширение. Следующее не работает:
@echo off
setlocal enableDelayedExpansion
set "line=<html>"
REM - the following command fails
cmd /v:on /c echo !test!|findstr .
Проблема в том, что !test!
это расширено в родительском скрипте, поэтому новый процесс CMD пытается проанализировать незащищенные <
и >
.
Вы можете избежать !
, но это может быть сложно, потому что это зависит от того, !
цитируется или нет.
Если не кавычки, то требуется двойной escape:
@echo off
setlocal enableDelayedExpansion
set "line=<html>"
cmd /v:on /c echo ^^!test^^!|findstr .
В кавычках используется единственный escape-код:
@echo off
setlocal enableDelayedExpansion
set "line=<html>"
cmd /v:on /c "echo ^!test^!"|findstr .
Но есть удивительный трюк, который позволяет избежать всех экранирований - включение левой части канала предотвращает !test!
преждевременное расширение родительского скрипта :
@echo off
setlocal enableDelayedExpansion
set "line=<html>"
(cmd /v:on /c echo !test!)|findstr .
Но я полагаю, что даже это не бесплатный обед, потому что пакетный синтаксический анализатор вводит дополнительное (возможно, нежелательное) пространство в конце, когда используются круглые скобки.
Не весело писать сценарии ;-)