Комментирование нескольких строк в пакетном файле DOS

98

Я написал огромный пакетный файл MS DOS. Чтобы протестировать этот командный файл, мне нужно выполнить только несколько строк и я хочу скрыть / закомментировать оставшиеся.

У меня есть некоторые существующие строки комментариев, начинающиеся с, ::поэтому я больше не могу их использовать ::, так как он скремблирует все комментарии.

Как я могу решить эту проблему?

user219628
источник

Ответы:

184

Вы можете использовать a, gotoчтобы пропустить код.

goto comment
...skip this...
:comment
pdubs
источник
11
+1: Забавно использовать для этого «goto», И это работает!
rap-2-h
1
Я думаю, что забавно, что в командной строке нет настоящего определения комментария, я просто не могу принимать REMстроки в качестве строк комментариев, это делает вывод неясным
mkb
126

Если вы хотите добавить REM в начале каждой строки вместо использования GOTO, вы можете использовать Notepad ++, чтобы сделать это легко, выполнив следующие действия:

  1. Выберите блок линий
  2. нажмите Ctrl-Q

Повторите шаги, чтобы раскомментировать

Cvacca
источник
6
Хороший совет. делает его намного чище.
Venom
1
Вау, не знал, что у Notepad ++ есть такая замечательная функция! На самом деле очень пропустил, потому что я привык к `Ctrl + 7 'в Eclipse. Проголосовало до 42 ;)
Дэнни Ло
1
Насчет раскомментирования. Там любой ярлык, чтобы раскомментировать весь блок.
Бхаскар Сингх
2
@BhaskarSingh Начиная с Notepad ++ 7.5.6, вы можете просто выделить уже прокомментированный текст; нажмите "Ctrl + Q", и он раскомментирует его
CreativiTimothy
Если ваш мозг часто слаб , как у меня , чтобы помнить Ctrl-Q, нажмите на Notepad++: Edit -> Comment/Uncomment.
Timo
13
break||(
 code that cannot contain non paired closing bracket
)

Хотя это gotoрешение является хорошим вариантом, оно не будет работать в квадратных скобках (включая команды FOR и IF), но это будет. Хотя вы должны быть осторожны закрывающих скобок и неправильного синтаксиса для FORи IFкоманд , так как они будут обрабатываться.

Обновить

Обновление в ответе dbenham дало мне несколько идей. Во-первых, есть два разных случая, когда нам могут понадобиться многострочные комментарии - в контексте скобок, где GOTO нельзя использовать, и вне его. Внутри скобок контекста мы можем использовать другие скобки , если есть условие , которое предотвращает код будет executed.Though код thede по- прежнему будет проанализирован и будут обнаружены некоторые синтаксические ошибки ( FOR, IF, неправильно закрытые скобки, неправильное расширение параметра ..). Таким образом , если есть возможность, лучше использовать GOTO.

Хотя невозможно создать макрос / переменную, используемую в качестве метки, но можно использовать макросы для комментариев в скобках. Тем не менее, можно использовать два трюка, чтобы сделать комментарии GOTO более симметричными и более приятными (по крайней мере, для меня). Для этого я использую два трюка: 1) вы можете поместить один символ перед меткой, и goto все равно сможет его найти (я понятия не имею, почему это так. Я думаю, он ищет диск). 2) вы можете поставить одиночный : символ в конце имени переменной, и функция замены / подстановки не будет активирована (даже при включенных расширениях). Это в сочетании с макросами для комментариев в скобках может сделать оба случая почти одинаковыми.

Итак, вот примеры (в том порядке, в котором они мне нравятся больше всего):

С прямоугольными скобками :

@echo off

::GOTO comment macro
set "[:=goto :]%%"
::brackets comment macros
set "[=rem/||(" & set "]=)"

::testing
echo not commented 1

%[:%
  multi 
  line
  comment outside of brackets
%:]%

echo not commented 2

%[:%
  second multi 
  line
  comment outside of brackets
%:]%

::GOTO macro cannot be used inside for
for %%a in (first second) do (
    echo first not commented line of the %%a execution
    %[%
        multi line
        comment
    %]%
    echo second not commented line of the %%a execution
)

С фигурными скобками :

@echo off

::GOTO comment macro
set "{:=goto :}%%"
::brackets comment macros
set "{=rem/||(" & set "}=)"

::testing
echo not commented 1

%{:%
  multi 
  line
  comment outside of brackets
%:}%

echo not commented 2

%{:%
  second multi 
  line
  comment outside of brackets
%:}%

::GOTO macro cannot be used inside for loop
for %%a in (first second) do (
    echo first not commented line of the %%a execution
    %{%
        multi line
        comment
    %}%
    echo second not commented line of the %%a execution
)

В скобках :

@echo off

::GOTO comment macro
set "(:=goto :)%%"
::brackets comment macros
set "(=rem/||(" & set ")=)"

::testing
echo not commented 1

%(:%
  multi 
  line
  comment outside of brackets
%:)%

echo not commented 2

%(:%
  second multi 
  line
  comment outside of brackets
%:)%

::GOTO macro cannot be used inside for loop
for %%a in (first second) do (
    echo first not commented line of the %%a execution
    %(%
        multi line
        comment
    %)%
    echo second not commented line of the %%a execution
)

Смесь между стилями powershell и C ( <не может использоваться, потому что перенаправление с более высоким приоритетом. *Не может использоваться из-за %*):

@echo off

::GOTO comment macro
set "/#:=goto :#/%%"
::brackets comment macros
set "/#=rem/||(" & set "#/=)"

::testing
echo not commented 1

%/#:%
  multi 
  line
  comment outside of brackets
%:#/%

echo not commented 2

%/#:%
  second multi 
  line
  comment outside of brackets
%:#/%

::GOTO macro cannot be used inside for loop
for %%a in (first second) do (
    echo first not commented line of the %%a execution
    %/#%
        multi line
        comment
    %#/%
    echo second not commented line of the %%a execution
)

Чтобы emphase это комментарий (мысль не так коротка):

@echo off

::GOTO comment macro
set "REM{:=goto :}REM%%"
::brackets comment macros
set "REM{=rem/||(" & set "}REM=)"

::testing
echo not commented 1

%REM{:%
  multi 
  line
  comment outside of brackets
%:}REM%

echo not commented 2

%REM{:%
  second multi 
  line
  comment outside of brackets
%:}REM%

::GOTO macro cannot be used inside for
for %%a in (first second) do (
    echo first not commented line of the %%a execution
    %REM{%
        multi line
        comment
    %}REM%
    echo second not commented line of the %%a execution
)
нпочмака
источник
1
Вы можете использовать rem.||(или rem^ (вместо. Намерение немного яснее. Смотрите мой обновленный ответ.
dbenham
@dbenham - да с rem короче.
npocmaka
1
Ох, квадратные и фигурные скобки сексуальны. Если бы я писал код только для себя, я бы его использовал. Но я полагаю, что средний пользователь увидит это и скажет «WTF».
dbenham 06
@dbenham - может быть, вы правы. Я могу добавить %rem:%+ %:rem%форму, чтобы сделать ее более очевидной, хотя она потеряет свое очарование. Или только косая черта, чтобы быть ближе к C-стилю ...
npocmaka
1
@npocmaka Это круто! Я только что изучил кучу тонкостей пакетного сценария, пока выяснял, что вы сделали. Из всех известных мне методов блочного комментирования (для пакетной обработки) этот кажется самым надежным и умным. +1 за совмещение хака и стиля
Джаред Готт
10

Другой вариант - заключить нежелательные строки в блок IF, который никогда не может быть истинным.

if 1==0 (
...
)

Конечно, внутри блока if ничего не будет выполнено, но будет проанализировано. Таким образом, у вас не может быть недопустимого синтаксиса внутри. Кроме того, комментарий не может содержать, )если он не экранирован или не заключен в кавычки. По этим причинам принятое решение GOTO более надежно. (Решение GOTO также может быть быстрее)

Обновление 2017-09-19

Вот косметическое усовершенствование решения GOTO от pdub . Я определяю простой «макрос» переменной среды, который делает синтаксис комментариев GOTO немного лучше самодокументированным. Хотя обычно рекомендуется, чтобы метки: были уникальными в рамках пакетного сценария, действительно допустимо встраивать несколько комментариев, подобных этому, в один пакетный сценарий.

@echo off
setlocal

set "beginComment=goto :endComment"

%beginComment%
Multi-line comment 1
goes here
:endComment

echo This code executes

%beginComment%
Multi-line comment 2
goes here
:endComment

echo Done

Или вы можете использовать один из этих вариантов решения npocmaka . Использование REM вместо BREAK немного проясняет замысел.

rem.||(
   remarks
   go here
)

rem^ ||(
   The space after the caret
   is critical
)
Dbenham
источник
1

Просто хочу отметить, что решение GOTO от pdub не совсем корректно в случае: метка комментария появляется несколько раз. Я изменяю код из этого вопроса в качестве примера.

@ECHO OFF
SET FLAG=1
IF [%FLAG%]==[1] (
    ECHO IN THE FIRST IF...
    GOTO comment
    ECHO "COMMENT PART 1"
:comment
    ECHO HERE AT TD_NEXT IN THE FIRST BLOCK
)

IF [%FLAG%]==[1] (
    ECHO IN THE SECOND IF...
    GOTO comment
    ECHO "COMMENT PART"
:comment
    ECHO HERE AT TD_NEXT IN THE SECOND BLOCK
)

Выход будет

IN THE FIRST IF...
HERE AT TD_NEXT IN THE SECOND BLOCK

Команда ECHO HERE HERE AT TD_NEXT В ПЕРВОМ БЛОКЕ пропускается.

Чарльз Чиу
источник
0

@jeb

И после этого stderr кажется недоступным

Нет, попробуйте это:

@echo off 2>Nul 3>Nul 4>Nul

   ben ali  
   mubarak 2>&1
   gadeffi
   ..next ?

   echo hello Tunisia

  pause

Но почему это работает?

извините, я отвечаю на вопрос по-французски:

(перенаправление из пункта 3> есть специальный автомобиль elle persiste, on va l'utiliser pour capturer le flux des erreurs 2> is on va le transformer en un flux persistant à l'ade de 3> ceci va nous permettre d'avoir une gestion des erreur pour tout notre environement de script..par la suite si on veux recuperer le flux 'stderr' il faut faire une autre redirection du handle 2> au handle 1> qui n'est autre que la console ..)

walid2mi
источник
1
Я не могу читать по-французски, но похоже, вы не объясняете, почему поток 2 (stderr) продолжает отключаться после завершения первоначального перенаправления. У меня есть работающая теория и контрольные примеры в двух последовательных сообщениях на dostips.com/forum/viewtopic.php?p=14612#p14612 .
dbenham
(Перенаправление на 3> является особенным, потому что оно сохраняется, мы будем использовать его для захвата потока ошибок 2> если оно превратит его в постоянный поток до значения 3> это позволит нам иметь ошибку управления для любого из наших сценарий окружения .. тогда, если вы хотите восстановить поток 'stderr', мы должны сделать другое перенаправление дескриптора 2> для обработки>, который является ничем иным, как консолью ..)
user96403
-1

попробуй это:

   @echo off 2>Nul 3>Nul 4>Nul

   ben ali
   mubarak
   gadeffi
   ..next ?

   echo hello Tunisia

  pause
walid2mi
источник
+1, а почему работает? И после этого stderr кажется недоступным
jeb
1
-1, это «работает», потому что echo 2> Nul перенаправляет стандартный поток ошибок на NUL, скрывая его (3> Nul, 4> Nul перенаправляют вспомогательные потоки без реальной причины). Это не комментирует строки, а просто предотвращает отображение сообщений об ошибках. Так что все, что можно интерпретировать как командные строки, все равно будет работать.
pdubs
3
Комментарий pdubs частично верен в том смысле, что команды все еще выполняются (и не работают, потому что недействительны). Но действительные команды будут выполняться без сбоев. Так что это не лучшее решение для комментирования строк кода. Объяснение того, почему поток 2 (stderr) "постоянно" отключен, неверно.
dbenham
3
У меня есть теория о том, как работает перенаправление в пакете Windows, и она объясняет, почему stderr становится «навсегда» отключенным в этом ответе. Теория и тесты находятся в 2-х постах подряд на dostips.com/forum/viewtopic.php?p=14612#p14612
dbenham