analysis: ":: is not the same as rem"

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
jeb
Expert
Posts: 1041
Joined: 30 Aug 2007 08:05
Location: Germany, Bochum

analysis: ":: is not the same as rem"

#1 Post by jeb » 04 May 2010 11:44

Hi,

I have made some experiments.

Perhaps someone find it usefull, interesting or totally boring. :)

1. Rem have a different behavior than ::
Example1: Bracket test

Code: Select all

(
rem this works
)
(
:: This stops with a sytax error, I suppose that :: is only a lable that can't be called
)


2. The text after a rem or :: is not ignored
Example:

Code: Select all

rem one^
echo this line will NOT printed

:: one^
echo this line will NOT printed

rem one two^
echo this line is printed, because only the first token(after the rem) is evaluated for multilines
:: one two^
echo this line will NOT printed, because after a lable all tokens are valid


3. Expansion of %var% works at every position in both, rem and ::

Code: Select all

set "multi=^^"
rem %multi%
echo this line will NOT printed

:: %multi%

rem one two %~error%
set longString=5000 characters
rem %longString% %longString%
rem this stops with a syntax error, because the line is too long


But delayed expansion does not work in rem or ::

Code: Select all

rem !multi!
echo this line will be displayed


That's because the expansion phase of ! is after the multiline phase.
(Expansion phases will be explained in another post)

Example2:
2. !emptyCommand! can create a rem effect, so that the rest of the line will be ignored

Code: Select all

setlocal EnableDelayedExpansion
set "emptyCommand="
!emptyCommand! echo This line will be ignored


And now all as one file "remarks.bat"

Code: Select all

@echo off
setlocal DisableDelayedExpansion
cls

if "%1" NEQ "" goto :remoteExecuter

echo The rules of remarks
echo\
echo A rem ignores  all after the first token, but wrong expressions can create an error like "rem one two %%~var%%
echo but the first token can contain a working multiline character
echo All tokens are expanded "%%variables%%", but only the first one can have an effect
echo A empty(remark) Token can be create with EnableDelayedExpansion and !EmptyCommand!
echo\
echo :: is not the same as rem
echo\

call :example remExample1
call :example remExample2
call :example remExample3
call :criticalExample remExample4
call :example remExample5
goto :eof

::###############################
:remExample1
rem IgnoreThis^
echo This line is also ignored, multiline with one token works
goto :eof
::End of function

::###############################
:remExample2
rem Ignore this^
echo This line is echo'd, the mutliline of rem more than one token does not work
goto :eof
::End of function

::###############################
:remExample3
set "remExp=Multiline^"
rem %remExp%
echo This line is also ignored, multiline with one token works, expansion phase is before rem

set "remExp=Multiline does not work^"
rem %remExp%
echo This line is echod, the mutliline of rem more than one token does not work
goto :eof
::End of function

::###############################
:remExample4
rem show that expansion of % in a line is before the rem ignores the rest of the line
rem The expansion results in a very long line with 10000 characters, that results in a syntax error, the batch stops immediatly
setlocal EnableDelayedExpansion
set "longStr=."
for /L %%c in (1,1,13) DO set longStr=!longStr:~0,2500!!longStr:~0,2500!
rem Now we heave a string with 5000 characters, and build a rem line with 2 times 5000 = 10000 characters
rem The next line crashes the batch file
rem tokenOne %longStr% %longStr%
(
   ENDLOCAL
   goto :eof
)
::End of function

::###############################
:remExample5
echo show that expansion of !emptyCommand! can create a rem effect, so that the rest of the line will be ignored
setlocal EnableDelayedExpansion
set "emptyCommand="
!emptyCommand! echo This line will be ignored
(
   ENDLOCAL
   goto :eof
)
::End of function

::################ TODO
:TODO
echo\
echo Rem test with Delayed expansion
set "sig=one two"
set "vType=type x"
set "rem=rem one two^"
set "x=&"
set REM
echo\--
setlocal EnableDelayedExpansion
echo REM is !REM! -
echo vType is !vType! -

goto :eof

goto :eof
############ END OF TODO
::End of function

::###############################
:example
call :showCode %~1
echo\--------------- begin of output of function :%~1
setlocal
call :%~1
endlocal
echo\--------------- end of output
echo\
echo Press any key
pause > nul
goto :eof
::End of function

::###############################
:executeRemote
start /min /wait cmd /c %~f0 %*
set remoteErrorlevel=%errorlevel%
goto :eof
::End of function

::###############################
:remoteExecuter
call %* 1> remoteExecute.log 2>&1
goto :eof
::End of function

::###############################
:criticalExample
setlocal
call :showCode %~1
call :executeRemote :%*
echo\--------------- begin of output of function :%~1
type remoteExecute.log
del remoteExecute.log 2> nul
echo\--------------- end of output, with ERRORLEVEL=%remoteErrorlevel%
echo\
echo Press any key
pause > nul
(
  endlocal
  goto :eof
)
::End of function

::###############################
:showCode
SETLOCAL DisableDelayedExpansion
rem Disable it to be able to echo "!" and "^"
echo\
echo ########## Example %~1 ################# Code of the example
set "found="
echo ---------------------
FOR /F "tokens=*" %%L IN (%~f0) DO (
  if "%%L" == ":%~1" set found=1
  rem setlocal EnableDelayedExpansion
  if defined found  (
    rem set "var=%%L"
    rem echo\   !var:^^=#!
   echo %%L
   if "%%L" == "::End of function" goto :showCode.break
  )
)
:showCode.break
echo ---------------------
echo\
(
  endlocal
  goto :eof
)
::End of function


hope it is not too boring
jeb

DosItHelp
Expert
Posts: 239
Joined: 18 Feb 2006 19:54

Re: analysis: ":: is not the same as rem"

#2 Post by DosItHelp » 10 May 2010 19:31

Interesting jep!

dostips should have a section for "interesting behaviors".
Another thing about rem is the effect of the dot:

Code: Select all

rem &echo this line will not be printed
rem.&echo this line will be printed

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: analysis: ":: is not the same as rem"

#3 Post by dbenham » 15 Apr 2012 15:54

DosItHelp wrote:Another thing about rem is the effect of the dot:

Code: Select all

rem &echo this line will not be printed
rem.&echo this line will be printed


8) I've seen this post before, but I never realized until now just how cool the REM. effect is.

You can put nearly any legal comment between REM. and & and still have the command work properly

Code: Select all

rem. Nearly any comment I want &echo This prints just fine!
All of the special characters still function after REM., so you must be careful with < > and | in the remark.


Dave Benham

jeb
Expert
Posts: 1041
Joined: 30 Aug 2007 08:05
Location: Germany, Bochum

Re: analysis: ":: is not the same as rem"

#4 Post by jeb » 15 Apr 2012 16:51

REM. is nice, but have a drawback.
If a file exists with the name REM (without extension), REM. results into a file not found error.

But you could use REM^: instead, that seems to work always.
Also the other batch delimiters seems to work this way

Code: Select all

REM^,&echo hello
REM^;&echo hello
REM^ &echo hello
REM^=&echo hello


I suppose the cause for the behaviour here is the parser in the "special charcter phase",
normally there will be a REM statement detected and the parsing stops.
But with a directly appended character the REM-detection fails, so the other phases will be executed.
But in the execution phase the REM will be finally recognized and the comment will be "executed".

BTW. My first post here is a bit outdated, somewhere I explained the full functionality of :: and how and why they can work inside of brackets.

jeb

Liviu
Expert
Posts: 470
Joined: 13 Jan 2012 21:24

Re: analysis: ":: is not the same as rem"

#5 Post by Liviu » 15 Apr 2012 21:36

jeb wrote:But you could use REM^: instead, that seems to work always.

Hmm... Not quite always. For one thing, it seems to be subject to the "\..\" issue.

Code: Select all

C:\tmp>dir /b dummy.*
dummy.cmd

C:\tmp>type dummy.cmd
@echo running %0

C:\tmp>rem^\..\dummy & echo 123
123

C:\tmp>rem^:\..\dummy & echo 123
123

C:\tmp>rem^\..\dummy.cmd & echo 123
running rem\..\dummy.cmd
123

C:\tmp>rem^:\..\dummy.cmd & echo 123
running rem:\..\dummy.cmd
123
The last two command lines show that "dummy.cmd" is run as "rem[:]\..\dummy.cmd".

As if this was not odd enough, creating an empty "dummy" file with no extension causes "dummy.cmd" to run even if no ".cmd" extension is given on the "rem" line explicitly.

Code: Select all

C:\tmp>copy nul dummy
        1 file(s) copied.

C:\tmp>rem^\..\dummy & echo 123
running rem\..\dummy
123

C:\tmp>rem^:\..\dummy & echo 123
running rem:\..\dummy
123

Guess I'd have long given up on batch language if it weren't for such wonderfully incomprehensible silliness ;-)

Liviu

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: analysis: ":: is not the same as rem"

#6 Post by dbenham » 15 Apr 2012 21:55

Anyone find a problem with using the escaped token delimiters :?:

I'm kind of partial to

Code: Select all

rem^ &echo my command


Dave Benham

Liviu
Expert
Posts: 470
Joined: 13 Jan 2012 21:24

Re: analysis: ":: is not the same as rem"

#7 Post by Liviu » 16 Apr 2012 18:34

dbenham wrote:Anyone find a problem with using the escaped token delimiters :?:

I thought this whole exercise was more about second-guessing the parsing rules, rather than making "rem" work. After all, a non-escaped 1st token like "rem # text-goes-here #" does work, including cases where the text starts with "/?" or ends with "^".

That said, one odd behavior of the escaped space seems to be this...

Code: Select all

C:\tmp>rem^ |more
'rem ' is not recognized as an internal or external command,
operable program or batch file.

Another case where parsing appears to work differently between the rem and echo internal commands is...

Code: Select all

C:\tmp>rem^ /?

C:\tmp>echo^ /?
Displays messages, or turns command-echoing on or off.

  ECHO [ON | OFF]
  ECHO [message]

Type ECHO without parameters to display the current echo setting.

Liviu

Post Reply