1

I am working on editing an XML file, and approximately the first 10 lines are comments. And for xml comments are in the form

<!--  COMMENT HERE   -->

But when using my code it does not output that ! mark, which screws up the comments in the xml. I understand that the ENABLEDELAYEDEXPANSION is doing this because it thinks the exclamation mark is expanding a variable. How could I get this to work?

Here is my code below

setlocal ENABLEDELAYEDEXPANSION

set line=0

FOR /f "usebackqdelims=" %%a in ("%filename2%") do (
    set /a line = !line!+1 
    if !line!==39 (echo REPLACED TEXT39>>%tempfile%
)else if(!line!==45 (echo REPLACED TEXT45>>%tempfile%
)else (echo %%a>>%tempfile%
))

EDIT1 Basically what it is supposed to do is output each line as it is, unless it is line 39 or 45. It works, except the ! marks in the comments don't get outputted and they are not comments anymore.

EDIT2

set line=0

FOR /f "usebackqdelims=" %%a in ("%filename2%") do (
setlocal ENABLEDELAYEDEXPANSION
    set /a !line! +=1
echo !line!
    if !line!==39 (
echo REPLACED TEXT39>>%tempfile%
endlocal
)else if !line!==45 (
echo REPLACED TEXT45>>%tempfile%
endlocal
)else (
endlocal
setlocal DISABLEDELAYEDEXPANSION
echo %%a>>%tempfile%
endlocal
))

Here is the latest code I have been using. It works the best, but now the problem is that the variable "line" is not getting updated. I have a feeling that it is because of the "endlocal". The only problem is that I need the "endlocal" there otherwise I get an error

Maximum setlocal recursion level reached.

The problem is, I need to alternate between enableddelayedexpansion and disabledelayedexpansion so that my exclamation marks show up properly. But to do that I need to keep up with the "endlocal" calls which i think is messing up my line variable. Any thoughts?

Jeremy Rowler
  • 387
  • 1
  • 5
  • 15

1 Answers1

5

You can't output the exclamation mark this way.

The exclamation mark is part of the content of %%a but while delayed expansion is enabled you can't access it, as it will be parsed after the %%a is epanded.

So you need to disable delayed expansion at all or temporary.

A sample for temporary disabling it

setlocal ENABLEDELAYEDEXPANSION

set line=0

FOR /f "usebackqdelims=" %%a in ("%filename2%") do (
    set /a line = !line!+1 
    if !line!==39 (
      echo REPLACED TEXT39>>%tempfile%
    ) else if !line!==45 (
      echo REPLACED TEXT45>>%tempfile%
    ) else (
      setlocal DisableDelayedExpansion
      echo %%a>>%tempfile%
      endlocal
    )
)

Or you don't use it at all, then you only need to get the if line=42 part working.
This uses the fact that modulo by 0, will produce an error (which is suppressed by 2>nul) and the variable stays unchanged, in this case they stay undefined.

setlocal DisableDelayedExpansion
set line=0

FOR /f "usebackqdelims=" %%a in ("%filename2%") do (
    set /a line+=1
    set "notLine39="
    set /a "notLine39=1%%(line-39)" 2>nul
    set "notLine45="
    set /a "notLine45=1%%(line-45)" 2>nul

    if not defined line39 (
      echo REPLACED TEXT39>>%tempfile%
    ) else if not defined line45 (
      echo REPLACED TEXT45>>%tempfile%
    ) else (
      setlocal DisableDelayedExpansion
      echo %%a>>%tempfile%
      endlocal
    )
)

Edit: Added explanation to your changed question
This uses the toggling delayed expansion technic, described in SO: Batch files: How to read a file?
The trick is to be in disabledDelayedExpansion when transfering %%a to text, then switching to enabledDE and be able to use the extended syntax.
But don't forget the endlocal before the next loop starts.

setlocal DisableDelayedExpansion
set line=0

FOR /f "usebackqdelims=" %%a in ("%filename2%") do (
    set /a line+=1
    set "text=%%a"
    setlocal EnableDelayedExpansion
    if !line!==39 (
      echo REPLACED TEXT39>>%tempfile%
    ) else if !line!==45 (
      echo REPLACED TEXT45>>%tempfile%
    ) else (
      echo %%a>>%tempfile%
    )
    endlocal
)
Community
  • 1
  • 1
jeb
  • 78,592
  • 17
  • 171
  • 225
  • Ok, the problem with this new one is that line39 will always be undefined, and it will always print out "REPLACED TEXT39", Im not sure how "set /a "notLine39=1%%%%(line-39)" 2>nul" This line is working, but is that setting it to null if it gets to the line? If it is, the maybe if we set something into notLine39 initially? that way the " if not defined line39" will only be true if it is on line 39? – Jeremy Rowler May 06 '14 at 17:12
  • Also after a short simple test echoing the line, it appears that it does not get incremented... – Jeremy Rowler May 06 '14 at 17:47
  • 1
    @JeremyRowler - There was a bug in the definition of notLineNN: too many percents. All fixed by removing two percents in two places. Answer has been updated. – dbenham May 06 '14 at 18:46
  • Thanks @dbenham, I played before with 'call set /a "notLine39=1%%%%(line-39)"' and errorlevel. And then I forgot to remove it :-) – jeb May 06 '14 at 21:03