Может кто-нибудь дать мне пример того, где пакет script будет действовать по-разному с или без задержки расширения? Есть ли ситуации, когда вы НЕ хотели бы использовать задержанное расширение? Спасибо.
Пример замедленного расширения в пакетном файле
Ответ 1
Посмотрите на следующие примеры...
Пример 1: Следующий код НЕ использует задержанное расширение, поэтому переменные в цикле for расширяются только один раз. Это означает, что %Count%
всегда будет расширяться до 0
на каждой итерации цикла, независимо от того, что мы делаем с ним командой set:
@echo off
set COUNT=0
for %%v in (1 2 3 4) do (
set /A COUNT=%COUNT% + 1
echo Count = %COUNT%
)
pause
Итак, этот script выведет:
Count = 0
Count = 0
Count = 0
Count = 0
Это не значит, что этот цикл должен работать.
Пример 2: С другой стороны, если мы используем задержанное расширение, мы имеем следующий script, который будет работать как ожидалось.
setlocal ENABLEDELAYEDEXPANSION
set COUNT=0
for %%v in (1 2 3 4) do (
set /A COUNT=!COUNT! + 1
echo Count = !COUNT!
)
pause
и, как ожидается, он выведет:
Count = 1
Count = 2
Count = 3
Count = 4
Когда вы используете ENABLEDELAYEDEXPANSION
и расширяете переменную с помощью !
вместо %
, переменная повторно разворачивается каждый раз, и все работает так, как предполагалось.
Ответ 2
Я хотел добавить отличный пример того, как "EnableDelayedExpansion" (EDE) может быть полезен вне вездесущих примеров цикла FOR.
Вот строка данных землетрясения, которую я хочу проанализировать (я называю это 1line.txt)
ak_11574812 2015.04.29.193822 62.9525 -148.8849 1.0 9.5 1 49km S Кантуэлл, Аляска
Проблема, с которой я столкнулся, заключалась в том, что последний сегмент этой строки не всегда начинается с одного и того же номера столбца. Поэтому мне нужно было создать гибкую команду SET, которая точно вырвет последний сегмент этой строки.
ECHO OFF
setlocal enableDelayedExpansion
set where=72
set /p line=<1line.txt
set locate=!line:~%where%,28!
echo %locate%
EDE позволяет мне поместить переменную (где) внутри другой переменной (строки). EDE сначала преобразует переменную с квадратом в%, а затем обработает переменную, заключенную в скобки! и (в этом случае) вытолкнуть результаты в переменную "locate".
Ответ 3
Максимальный ответ дает пример того, где пакет script будет действовать по-разному с задержкой или без него.
Для полноты позвольте ответить на другую часть вопроса и показать ситуацию, когда вы не захотите использовать задержанное расширение, когда ваши данные содержат восклицательный знак !
(и показывают два способы обработки таких данных):
@ECHO OFF
SETLOCAL EnableExtensions DisableDelayedExpansion
set "_auxFile=%temp%\%~n0.txt"
rem create multiline sample file
>"%_auxFile%" ( for /L %%G in (1,1,3) do echo line %%G is 100%% valid! Sure! Hurrah!)
rem create one-line sample file
>"%_auxFile%" echo this line is 100%% valid! Sure! Hurrah!
echo(
echo --- file content
type "%_auxFile%"
echo(
SETLOCAL EnableDelayedExpansion
echo --- enabled delayed expansion chokes down unescaped exclamation marks^^^! "^!"
for /F "usebackq delims=" %%G in ("%_auxFile%") do (
set "_auxLine=%%~G"
echo loop var=%%~G
echo _auxLine=!_auxLine!
)
ENDLOCAL
echo(
SETLOCAL DisableDelayedExpansion
echo --- toggled delayed expansion works although might be laborious!
for /F "usebackq delims=" %%G in ("%_auxFile%") do (
set "_auxLine=%%G"
echo loop var=%%G
SETLOCAL EnableDelayedExpansion
echo _auxLine=!_auxLine!
ENDLOCAL
)
ENDLOCAL
echo(
SETLOCAL DisableDelayedExpansion
echo --- keep delayed expansion DISABLED: use CALL command!
for /F "usebackq delims=" %%G in ("%_auxFile%") do (
set "_auxLine=%%G"
echo loop var=%%G
call :ProcessVar
)
ENDLOCAL
rem delete the sample file
del "%_auxFile%"
ENDLOCAL
goto :eof
:ProcessVar
echo _auxLine=%_auxLine%
echo WARNING: neither !_auxLine! nor %%G loop variable is available here!
goto :eof
Обратите внимание, что выше script показывает правильные способы экранирования
-
%
знак процента%%
удваивает его (отсроченное расширение не имеет значения) и -
!
восклицательный знак, если включено замедленное расширение:-
"^!"
, если он заключен в пару двойных кавычек, затем используйте общий escape-символcmd
и batch-script^
caret; -
^^^!
в противном случае используйте три^
.
-
Выход
==> D:\bat\SO\10558316.bat
--- file content
this line is 100% valid! Sure! Hurrah!
--- enabled delayed expansion chokes down unescaped exclamation marks! "!"
loop var=this line is 100% valid Hurrah
_auxLine=this line is 100% valid Hurrah
--- toggled delayed expansion works although might be laborious!
loop var=this line is 100% valid! Sure! Hurrah!
_auxLine=this line is 100% valid! Sure! Hurrah!
--- keep delayed expansion DISABLED: use CALL command!
loop var=this line is 100% valid! Sure! Hurrah!
_auxLine=this line is 100% valid! Sure! Hurrah!
WARNING: !_auxLine! as well as %G loop variables are not available here!
==>