Мне нравится использовать блоки команд, заключенные в круглые скобки, так как это позволяет мне передавать вывод всех команд в блоке в more
(или любую другую команду) одновременно.
Обычно я могу добавлять примечания (rem
) и внутри этих блоков.
Однако я не могу совместить эти две функции: блок с примечаниями, переданными в more
(или любую другую команду), вообще не выполняется. Почему это? Можно ли это решить?
@echo off
rem This works (prints X1)
(
echo X1
)
rem This works (prints X2)
(
echo X2
) | more
rem This works (prints X3)
(
rem
echo X3
)
rem Why does this print nothing?
(
rem
echo X4
) | more
rem Or this?
(
echo X4
rem
) | more
rem This works (prints X5)
(
:: Using colons instead of rem
echo X5
) | more
Это из-за складывания.
Использование каналов приводит к созданию двух отдельных дочерних процессов cmd.exe.
Но код должен быть свернут, прежде чем он будет передан в cmd.exe, особенно блоки кода.
Правило складывания простое, каждая новая строка будет переведена в амперсанд.
Так выглядит сложенный блок
( echo X1 & echo X2 )
Но с REM вы получаете
( REM & echo X4 )
REM помечает остальную часть строки, амперсанд больше не действует, и закрывающая скобка также помечается.
Если REM после этого ECHO, это та же проблема.
( echo X4 & REM )
Последняя часть отмечена, поэтому есть только ( echo X4
и отсутствует закрывающая скобка.
Но почему ::
комментарии работают?
Похоже, ::
должна привести к той же ошибке, что и REM
, но это работает!
Это потому, что метки ::
полностью удалены из блока кода, поэтому результирующая строка для блока, подобного
(
:: My comment
echo X4
)
Результаты просто:
C:\Windows\system32\cmd.exe /S /D /c" ( echo X4 )"
Как заставить REM работать в конвейерных блоках?
Самый простой способ — использовать REM.
, но это не совсем настоящий REM
, он не может закомментировать амперсанд или другие специальные символы.
(
REM. This is a comment, special characters aren't allowed here
echo This works
) | more
Или используйте дополнительный перевод строки в строке REM
(set \n=^
%=THIS LINE IS REQUIRED=%
)
(
REM This is a comment with & and | %%\n%% BREAK
echo This works
) | more
Как отлаживать свернутые блоки?
Это просто с псевдопеременной cmdcmdline
(
echo Debug %%cmdcmdline%%%
echo one
echo two
) | findstr /n "^"
Результат:
1:Отладка C:\Windows\system32\cmd.exe /S /D /c" ( эхо отладки %cmdcmdline% & echo one & echo two )"
2: один
3: два
См. также Почему отложенное расширение не работает, когда оно находится внутри конвейерного блока кода?
Это объяснение звучит разумно, но оно не объясняет, почему блок кода не выполняется с echo X4
, за которым следует (не предшествует) rem
, не так ли? Потому что echo X4 & rem
в одной строке отлично работает за пределами блока. Или в этом случае отмечены закрывающие скобки?
@bers я добавил дополнительное объяснение для этого случая
Очаровательный. Если редиректор
>
, он работает как положено. Мне кажется, это проблема @jeb...