ECHO ON / OFF behavior within a loop

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
mirrormirror
Posts: 129
Joined: 08 Feb 2016 20:25

ECHO ON / OFF behavior within a loop

#1 Post by mirrormirror » 01 Jul 2016 23:16

Does a FOR loop disable ECHO ON / OFF functionality, or "delay" it? Running this code looks like it should produce some screen output but I get nothing:

Code: Select all

@echo off & setlocal enableDelayedExpansion
for /f "tokens=1,2 delims=: " %%A in (
  'ipconfig /all ^| jrepl "%srcIP%[\s\S]*?^[ \t]*?DNS Servers (?:\. )+:(([\s\r\n]+(\d+\.){3}\d+)+)" $1 /m /jmatch ^| findstr /n "^"'
) do (
   @ECHO ON
  set "DNSServer.Cnt=%%A"
  set "DNSServer.%%A=%%B"
   @ECHO OFF
)

If there a way to turn on ECHO within for loops?

pieh-ejdsch
Posts: 240
Joined: 04 Mar 2014 11:14
Location: germany

Re: ECHO ON / OFF behavior within a loop

#2 Post by pieh-ejdsch » 02 Jul 2016 02:39

A for Loop is one Line, DO is the same Line to.
Before this line execute Echo ON will Show this line .
Echo OFF just execute this line.
ECHO ON/OFF works only line-by-line.
Use echo set ...

Code: Select all

:SetEchoBack
@setlocal
@ :: Liest ob ECHO ON oder OFF geschalten ist um Variablen zu setzen
@(
echo>"%temp%\isOn.Ft"
for /f "usebackq tokens=2 delims=()" %%E in ("%temp%\isOn.FT") do @set "EchoBack=echo %%E &"
del "%temp%\isOn.Ft"
set prompt=$G$S
)
@echo on
set N=2
:readin
call :checkEchoOn
%mon% >nul see this when Echo ON
echo
(
  echo in Loop
  %mon% set ab=xy
  echo on
  set cd=ui
  echo
  if %N% equ 1 (echo off
    echo
  )
  call :checkEchoOn
)
%mon% >nul see this when Echo is on
%mon% will echo when Echo OFF
echo
call :checkEchoOn
%mon% End loop

if %N% equ 2 set N=1 &echo off&goto :readin


:checkCMDline
:: setzt eine Variable CMDPause wenn im Batchmodus
@echo off
setlocal disabledelayedexpansion
 rem CMD-Kontex ?
set "CMDPause=%~f0"
set "CMDPause=%CMDPause:\=\\%"
set "CMDPause=%CMDPause:.=\.%"
setlocal enabledelayedexpansion
for /f delims^= %%i in ("!CMDcmdLine!") do endlocal &set "CMDPin=%%i"
cmd /von /c "echo !CMDPin!" |findstr /irc:"cmd .*\/c \"\"%CMDPause%\" .*\"" /c:"cmd\.exe .*\/c \"\"%CMDPause%\" .*\"" >nul &&endlocal &&set "CMDPause=pause &" ||endlocal &&set "CMDPause="
%EchoBack%
%CMDPause% exit /b

:checkEchoOn
%= @rem :: Liest ob ECHO ON oder OFF geschalten ist um Variablen zu setzen =%
@(
rem ^%Mon% Zeilen bei Echo on auf REM umschalten
echo>"%temp%\isOn.Ft"
< "%temp%\isOn.Ft" find "ON" >nul && set "Mon=rem" || set "Mon=echo("
del "%temp%\isOn.Ft"
exit /b
)
Last edited by pieh-ejdsch on 02 Jul 2016 07:54, edited 2 times in total.

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

Re: ECHO ON / OFF behavior within a loop

#3 Post by dbenham » 02 Jul 2016 07:51

mirrormirror wrote:Does a FOR loop disable ECHO ON / OFF functionality, or "delay" it? ...
If there a way to turn on ECHO within for loops?

You actually have it sort of backwards :wink:

The behavior you are seeing has nothing to do with the FOR loop.
Statements are echoed while they are parsed, so ECHO must generally be ON before parsing begins if you want to see the statements echoed. A block of statements involving parentheses and/or & is parsed all at once, so toggling ECHO ON and OFF within the block appears to have no effect.

Here are some examples without FOR loops that demonstrate the issue:

Code: Select all

@echo off

(
  echo on
  rem 1 - This is NOT echoed
  echo off
)

echo on & rem.2 - This is NOT echoed & echo off
--NO OUTPUT--

But there is one exception that arises from the fact that the DO portion of a FOR loop has its own ECHO phase that fires an additional time for each iteration.

Note how the entire FOR statement is echoed once, and then the DO portion is echoed an additional two times:

Code: Select all

@echo on
for %%N in (1 2) do rem %%N
--OUTPUT--

Code: Select all

C:\test>for %N in (1 2) do rem %N

C:\test>rem 1

C:\test>rem 2

The ECHO state is checked before each iteration to see if the DO code should be echoed. We can use that fact to accomplish effective ECHO toggling within a block of statements by adding a dummy FOR loop 8)

Code: Select all

@echo off

(
  echo on
  for %%. in (dummy) do rem 3 - This IS echoed
  echo off
)

echo on & (for %%. in (dummy) do rem.4 - This IS echoed) & echo off
--OUTPUT--

Code: Select all

C:\test>rem 3 - This IS echoed

C:\test>rem.4 - This IS echoed

Here is the solution applied to your original code.

Code: Select all

@echo off & setlocal enableDelayedExpansion
for /f "tokens=1,2 delims=: " %%A in (
  'ipconfig /all ^| jrepl "%srcIP%[\s\S]*?^[ \t]*?DNS Servers (?:\. )+:(([\s\r\n]+(\d+\.){3}\d+)+)" $1 /m /jmatch ^| findstr /n "^"'
) do (
  echo on
  for %%. in (dummy) do (
    set "DNSServer.Cnt=%%A"
    set "DNSServer.%%A=%%B"
  )
  echo off
)

Note how the ECHO ON/OFF statements are not within the inner loop, so you don't need the @ because they will not be echoed anyway :D

If you want to get rid of the echoed parentheses and odd spacing, then use a separate dummy FOR loop for each statement that you want to echo.

Code: Select all

@echo off & setlocal enableDelayedExpansion
for /f "tokens=1,2 delims=: " %%A in (
  'ipconfig /all ^| jrepl "%srcIP%[\s\S]*?^[ \t]*?DNS Servers (?:\. )+:(([\s\r\n]+(\d+\.){3}\d+)+)" $1 /m /jmatch ^| findstr /n "^"'
) do (
  echo on
  for %%. in (dummy) do set "DNSServer.Cnt=%%A"
  for %%. in (dummy) do set "DNSServer.%%A=%%B"
  echo off
)



Dave Benham

Post Reply