ABC
ABC

Reputation: 159

How to handle ! with enabledelayedexpansion in batch

I am trying to read a file using enabledelayedexpansion .File contains special character.Because of enabledelayedexpansion ! and text after that is ignored .Please suggests some way by which this issue can be resolved . note :- i have to use enabledelayedexpansion .

`

 @echo off 
set "search1='"
set "search2=""
set "search3=&"
set "search4=<"
set "search5=>"
set "search6=!"
set "replace1=&apos;"
set "replace2=&quot;"
set "replace3=&amp;"
set "replace4=&lt;"
set "replace5=&gt;"
set "replace6=^!"
setlocal enabledelayedexpansion 
set "textfile=!input!"
set "newfile=!input!1"
echo !textfile!
echo !newfile!
break>"!newfile!" 


(for /f  "delims=" %%i in (!textfile!) do (

    setlocal enabledelayedexpansion
        set "line=%%i"

    for /f "usebackq tokens=1,2 delims=$" %%a in ('"!search3!"$"!replace3!"') do set "line=!line:%%~a=%%~b!"
    for /f "usebackq tokens=1,2 delims=$" %%a in ('"!search4!"$"!replace4!"') do set "line=!line:%%~a=%%~b!"
    for /f "usebackq tokens=1,2 delims=$" %%a in ('"!search5!"$"!replace5!"') do set "line=!line:%%~a=%%~b!"
   for /f "usebackq tokens=1,2 delims=$" %%a in ('"!search2!"$"!replace2!"') do set "line=!line:%%~a=%%~b!"
  for /f "usebackq tokens=1,2 delims=$" %%a in ('"!search1!"$"!replace1!"') do set "line=!line:%%~a=%%~b!"


  setlocal enabledelayedexpansion
        echo(!line!
    endlocal
    ))>>"!newfile!"

Above is just part of script. textfile will contain file path.rest all substitution are working fine only in case of ! its causing issue

Upvotes: 3

Views: 1366

Answers (3)

jeb
jeb

Reputation: 82307

To read content from a file without destroying it you need to use the delayed toggling technic or reading it with set /p.

setlocal DisableDelayedExpansion
(
  for /f "delims=" %%i in (textfile.txt) do (
    set "line=%%i"  -- This must be done while delayed expansion is disabled
    setlocal EnableDelayedExpansion
    set "line=!line:<=&lt;!"
    echo(!line!
    endlocal
  )
) > outfile.txt

The toggeling is necessary, because the expansion of a FOR loop variable is only safe in the disabled delayed expansion mode, else exclamation marks are removed/interpreted.

Upvotes: 3

Aacini
Aacini

Reputation: 67216

Reading a file via SET /P is another way to avoid the problems related to Delayed Expansion that may be simpler than FOR /F. I also show you a simpler way to define the set of replacements via an array

@echo off
setlocal EnableDelayedExpansion

rem Define the set of replacements
set "replacA[&]=&amp;"
set "replace[']=&apos;"
set replace["]=&quot;
set "replace[<]=&lt;"
set "replace[>]=&gt;"
REM set "replace[!]=^!"   // Not needed

set "textfile=!input!"
set "newfile=!input!1"
echo !textfile!
echo !newfile!

call :ProcessFile < "!textfile!" > "!newfile!"
goto :EOF


:ProcessFile
set empty=0
set "line="
:emptyLine
set /P line=

if not defined line (
   set /A empty+=1
   if !empty! gtr 2 exit /B
   echo/
   goto emptyLine
)

for /F "tokens=2,3 delims=[]=" %%a in ('set replac') do set "line=!line:%%a=%%b!"
echo !line!
goto ProcessFile

The most complex part in :ProcessFile subroutine is just used to preserve a maximum of 2 empty lines together (that may easily be increased to more lines, if needed).

Upvotes: 1

JosefZ
JosefZ

Reputation: 30113

Edit: completely overwritten. I could either keep an ! exclamation mark in output or replace it by ^^! (or ^^^^!, ^^^^^^! etc.) with even number of ^^ carets as follows:

@ECHO OFF >NUL
SETLOCAL enableextensions enabledelayedexpansion
set "textfile=files\31130282textfile.txt"
set "newfile=files\31130282textfileNew.txt"
set "line="
set "quote=""
setlocal DisableDelayedExpansion
  set "exclamation=!"
  set "exclamationNew=%~1!"
  (for /f  "delims=" %%i in (%textfile%) do (
    set "line=%%i"
    SETLOCAL enabledelayedexpansion
      set "line=!line:&=&amp;!"
      set "line=!line:<=&lt;!"
      set "line=!line:>=&gt;!"
      call set "line=%%line:!quote!=&quot;%%"
      set "line=!line:'=&apos;!"
      call set "line=%%line:!exclamation!=!exclamationNew!%%"
      echo(!line!
    ENDLOCAL
  ))>"%newfile%"
endlocal
type "%newfile%"

Output:

==>type files\31130282textfile.txt"
<'abc'>&"cde"T
"<x!y!z!>"

==>D:\bat\SO\31130282.bat ""
&lt;&apos;abc&apos;&gt;&amp;&quot;cde&quot;T
&quot;&lt;x!y!z!&gt;&quot;

==>D:\bat\SO\31130282.bat "^"
&lt;&apos;abc&apos;&gt;&amp;&quot;cde&quot;T
&quot;&lt;x^^!y^^!z^^!&gt;&quot;

==>D:\bat\SO\31130282.bat "^^"
&lt;&apos;abc&apos;&gt;&amp;&quot;cde&quot;T
&quot;&lt;x^^^^!y^^^^!z^^^^!&gt;&quot;

Upvotes: 0

Related Questions