copy txt file and modify multiple lines

December 16, 2009 at 19:06:45
Specs: Windows XP, 4gb
Hello,

I am hoping someone can help with this.

I currently have a script that reads a txt file and writes to a new file. While it does that it also allows me to modify a single line number in the process. I need to change the script to modify more then one line number.( !N! = 94,22,36) (For performance reasons, preferably in the same pass. IE: Not it reads the txt file and writes, then reads and writes)

Here is the code that is relevant:

ECHO MODIFYING BINDINGS.XML
ECHO.
ECHO THIS PROCESS MAY TAKE A FEW MINUTES
ECHO.
setLocal EnableDelayedExpansion > %BINDLOC%\MOD_BINDINGS.XML

for /f "tokens=* delims= " %%a in (%BINDLOC%\BINDINGS.XML) do (
set /a N+=1
if !N! equ 94 (
echo ^<property name="port"^>%REMCLASSSVC%^</property^> >>%BINDLOC%\MOD_BINDINGS.XML
) else (
echo %%a>> %BINDLOC%\MOD_BINDINGS.XML
)
)
GOTO END


See More: copy txt file and modify multiple lines

Report •

#1
December 16, 2009 at 20:43:52
set lines=,94,22,36,
set /a nn=0
for /f %%a in (infile.xml) do (
set /a nn+=1
set test=!lines!
set cc=,!nn!,
call :fubar
if !test! neq !lines! set /p ze=line is to be changed !nn!:
)
goto :EOF
:fubar
set test=!lines:%cc%=!


now i'm waiting for M2 to bomb me with a one-liner version... LOL


Report •

#2
December 17, 2009 at 05:39:34
How is that supposed to work with the 'if' 'else' statement thouse as your calling another internal procedure? This is supposed to write the file from (infile.xml) to (infile2.xml) . Copy line for line except for the lines that I specificy (94,22,36) where it will replace those lines with the text I provide.

Thanks.


Report •

#3
December 17, 2009 at 08:18:54
I think the original one is good enough, but at the point of performing the IF statement:

if !N! equ 94

... I would use a call statement there, example:

if !N! equ 94 call :routine1
if !N! equ 22 call :routine1
if !N! equ 36 call :routine1

An then make "routine1" to be

echo ^<property name="port"^>%REMCLASSSVC%^</property^> >>%BINDLOC%\MOD_BINDINGS.XML

The 3 IF statements can be one, I guess, if you use some kind of OR statement


Report •

Related Solutions

#4
December 17, 2009 at 09:17:34
Thank you for your response. If that is done it would look similar to this:

ECHO MODIFYING BINDINGS.XML
ECHO.
ECHO THIS PROCESS MAY TAKE A FEW MINUTES
ECHO.
setLocal EnableDelayedExpansion > MOD_BINDINGS.XML

for /f "tokens=* delims= " %%a in (BINDINGS.XML) do (
set /a N+=1 (
if !N! equ 1 call :routine1
if !N! equ 2 call :routine2
if !N! equ 3 call :routine3
)
) else (
echo %%a>> MOD_BINDINGS.XML
)
GOTO END

:ROUTINE1
echo THIS MODIFIED LINE 1 >> MOD_BINDINGS.XML

:ROUTINE2
echo THIS MODIFIED LINE 2 >> MOD_BINDINGS.XML

:ROUTINE3
echo THIS MODIFIED LINE 3 >> MOD_BINDINGS.XML

:END
PAUSE
EXIT

--The problem is though that the else statement would get ignore then. This works with the exception of it doesn't copy any of the additional information form the original file.


Report •

#5
December 17, 2009 at 09:25:30
You're right, something else must be done there ... hmmm


for /f "tokens=* delims= " %%a in (BINDINGS.XML) do (
set /a N+=1
if NOT !N! equ 22 if NOT !N! equ 36 if NOT !N! equ 94 call :regular
if !N! equ 22 call :routine1
if !N! equ 36 call :routine2
if !N! equ 94 call :routine3
)
GOTO END

:regular
echo %%a>> MOD_BINDINGS.XML


Report •

#6
December 17, 2009 at 10:13:14
Still does not work. It outputs the modified lines but does not pass the unmodified lines.

Report •

#7
December 17, 2009 at 13:44:59
There's something wrong with that counter N

Report •

#8
December 17, 2009 at 14:01:27
OK, This one works, note I changed the line numbers:

@echo off & setLocal EnableDelayedExpansion


set N=0
del MOD_BINDINGS.XML

for /f "tokens=* delims= " %%a in (BINDINGS.XML) do (
set /a N=N+1
echo !N!
if NOT !N! equ 2 if NOT !N! equ 4 if NOT !N! equ 6 call :regular %%a
if !N! equ 2 call :routine1
if !N! equ 4 call :routine2
if !N! equ 6 call :routine3
)

GOTO END

:regular
echo %1>> MOD_BINDINGS.XML
GOTO :EOF

:ROUTINE1
echo THIS MODIFIED LINE 1 >> MOD_BINDINGS.XML
GOTO :EOF

:ROUTINE2
echo THIS MODIFIED LINE 2 >> MOD_BINDINGS.XML
GOTO :EOF

:ROUTINE3
echo THIS MODIFIED LINE 3 >> MOD_BINDINGS.XML
GOTO :EOF

:end

type MOD_BINDINGS.XML


Report •

#9
December 17, 2009 at 14:07:36
OOPS!
as usual, big oops. further examination of using ERRORLEVEL has led me to the conclusion that it doesn't work (for the posted code, anyway). modifying the foll. code to circumvent relying on it.

when i posted first, i thought you were making the same change to all three lines. if you have different mod's to apply to the 3 lines specified (94, 22, 36) then this might work.

set outfiel=%BINDLOC%\MOD_BINDINGS.XML
set /a nn=0
for /f %%a in (%BINDLOC%\bindings.xml) do (
set /a flag=0
set /a nn+=1
call :!nn! 2>nul
if !flag!==0 echo %%a >> !outfile!
)
goto :ex
:22
echo modifiedline22 >> !outfile!
goto :ex
:36
echo modifying line 36 >> !outfile!
goto :ex
:94
echo ^<property name="port"^>%REMCLASSSVC%^</property^> >>%BINDLOC%\MOD_BINDINGS.XML
goto :ex
:ex
set /a flag=1

just another way of doing what tvc's code does, but since his is working i recommend using it. (i just like to finish things when i start them so i went ahead and posted this)


Report •

#10
December 18, 2009 at 03:23:06
Initially I indeed thought that the 3 exceptions needed the same change being made, but I was wrong there. The code then became more complex indeed, but still, nothing special.


Report •

#11
December 18, 2009 at 12:29:52
Everyone thanks for your help, however this still doesn't work, were getting there though.

--tvc

So the problem now is that it doesn't pass the remaining lines properly as it did in the original batch file. It cuts the line off after the first space using your method.

example:

Let's say the bindings.xml file contains this:
THIS IS LINE 1
THIS IS LINE 2
THIS IS LINE 3
THIS IS LINE 4
THIS IS LINE 5

I'm using your code to modify lines 2,3,4

When passed through the script the mod_bindings.xml would result in this output:

THIS
THIS IS my modified text2
THIS IS my modified text3
THIS IS my modified text4
THIS


Report •

#12
December 18, 2009 at 19:08:15
it might be that sneaky little space in the "delims=" clause:
for /f "tokens=* delims= " %%a in (BINDINGS.XML) do (

just send him out the door!
for /f "tokens=* delims=" %%a in (BINDINGS.XML) do (


Report •

#13
December 19, 2009 at 05:19:40
That would probably because I had this in the code:

echo %1>> MOD_BINDINGS.XML

It only copies the first parameter, separated by a whitespace, to file MOD_BINDINGS.XML

It may be better to replace

if NOT !N! equ 2 if NOT !N! equ 4 if NOT !N! equ 6 call :regular %%a

with

set text=%%a
if NOT !N! equ 2 if NOT !N! equ 4 if NOT !N! equ 6 call :regular

and inside the subroutine:

echo %text%>> MOD_BINDINGS.XML


Report •

#14
December 23, 2009 at 14:12:06
Still no luck.

Error:
1
>> was unexpected at this time.

Tried removing the output just to have it echo and still erorrs obviously without the '>>' though, just error 1


Report •

#15
December 23, 2009 at 14:36:16
Just put the content of the script as you have it now, and go from there

Report •

#16
December 23, 2009 at 21:46:12
@tvc, i think you just got "crossed-up" with %%a and %1.
:regular
echo %1>> MOD_BINDINGS.XML

as you know, %1 is parameter #1 passed from commandline.
%%a i believe is what you meant. %1 does not exist unless the typer put it there at cmdline prompt.

FWIW here's the code that i corrected (again) from response #9 (don't ask me how i left 'tokens..' out, i've no clue!)
(just humor me, i like to tie up loose ends when i can...)

set outfile=%BINDLOC%\MOD_BINDINGS.XML
set /a nn=0
for /f "tokens=* delims=" %%a in (%BINDLOC%\bindings.xml) do (
set /a flag=0
set /a nn+=1
:: call label named nn.. if it fails (no label nn exists), then
:: the line is a "regular", flag will be 0 and therefore the line
:: is reiterated without modifications.
call :!nn! 2>nul
if !flag!==0 echo %%a >> !outfile!
)
goto :ex
:22
echo modifiedline22 >> !outfile!
goto :ex
:36
echo modifying line 36 >> !outfile!
goto :ex
:94
echo ^<property name="port"^>%REMCLASSSVC%^</property^> >>%BINDLOC%\MOD_BINDINGS.XML
goto :ex
:ex
set /a flag=1


Report •

#17
December 24, 2009 at 10:25:48
nbrane -- Closest we have got so far , but still not there.

It does everything beautifully except it removes all '!' from the script. This would be fine if it were just comments, but some of the XML contains '!'.

Here is section of the script currently that woulds minus the '!' issue:
__________________________________
set bindloc=C:\TEMP\jboss-5.0.1.GA\server\primaveraweb\conf\bootstrap

@echo off & setLocal EnableDelayedExpansion


del %bindLoc%\MOD_BINDINGS.XML

set outfile=%BINDLOC%\MOD_BINDINGS.XML
set /a nn=0
for /f "tokens=* delims=" %%a in (%BINDLOC%\bindings.xml) do (
set /a flag=0
set /a nn+=1
:: call label named nn.. if it fails (no label nn exists), then
:: the line is a "regular", flag will be 0 and therefore the line
:: is reiterated without modifications.
call :!nn! 2>nul
if !flag!==0 echo %%a >> !outfile!
)
goto :ex
:22
echo modifiedline22 >> !outfile!
goto :ex
:36
echo modifying line 36 >> !outfile!
goto :ex
:94
echo ^<property name="port"^>%REMCLASSSVC%^</property^> >>%BINDLOC%\MOD_BINDINGS.XML
goto :ex
:ex
set /a flag=1


Report •

#18
December 24, 2009 at 12:55:14
the "set / enabled" zapped the value between the exlms. i redid it to not use delayed expansion:

@echo off & setlocal
set %bindloc%=\work
set outfile=%BINDLOC%\MOD_BINDINGS.XML
set /a nn=0
for /f "tokens=* delims=" %%a in (%BINDLOC%\BINDINGS.XML) do (
call :uuu)
goto :EOF

:uuu
set /a flag=0
set /a nn+=1
call :%nn% 2>nul
if %flag%==0 for /l %%z in (1 1 1) do echo %%a>>%outfile%
goto :eof

:22
echo modifiedline%nn%>>%outfile%
goto :ex
:36
echo modifying line %nn% >>%outfile%
goto :ex
:94
echo ^<property name="port"^>%REMCLASSSVC%^</property^> >>%BINDLOC%\MOD_B.XML
goto :ex
:ex
set /a flag=1

//*end batchscript #1
note that it still zaps blank lines!
i also observed that: 1) blank lines at the end of the input file caused a ECHO IS OFF to go to outputfile
2) if you do: echo testing 6>>outfile it goes to screen instead of outfile (the 6 is interpreted as an alternate output i think)
if you put a space after the 6 it works but you get a blank at the end of the line.
I tried to mess it up by putting percents in the input file and it seemed to digest them properly
I had to do that goofy trick with the fake for-loop inside :uuu because %%a handled the <...> but if i put %%a into a variable, the < and > got interpreted as pipes and caused error.

after some more experimentation, i managed to do away with the for-loop and the flag variable by strategic use of endlocal: (this is a whole separate version, not part of #1 above):

@echo off & setlocal
del mod_b.xml
set remclasssvc=remclass
set bindloc=\work
set outfile=%BINDLOC%\MOD_B.XML
set /a nn=0
for /f "tokens=* delims=" %%a in (f.xml) do (
set xx=%%a
set /a nn+=1
setlocal enabledelayedexpansion
call :!nn! 2>nul
echo !xx!>>%outfile%
endlocal
)

:4
set xx=modifiedline%nn%
goto :ex
:8
set xx=modifying line %nn%
goto :ex
:12
set xx=^<property name="port"^>%REMCLASSSVC%^</property^>
goto :ex
:ex

further observation: apparently setlocals are cumulative, ie they "stack up" unless endlocal is used. I encountered the "maximum setlocal recursion" when endlocal was not used.


Report •

#19
December 25, 2009 at 04:27:01
Why would this script need SETLOCAL actually ?

Report •

#20
December 26, 2009 at 00:00:15
@tvc: it's not a big thing, but I just don't like having my work laying around out in the environment. sometimes i get reallyreallymad and i use expletives for var.names (embarassed to say!). plus if they are "out there", they (variables) can overrride your local ones and cause confusion, so i always always always setlocal unless i really want it put into the system environment. (I've had these things bite me on the ass too many times!). the other option (enabledel) is a whole different thread.

Report •

#21
December 26, 2009 at 08:09:47
I never had problems with them ... Windows doesn't have that many variables, just look 'em up with SET and remember to not use them in any script ... it's not that hard.

Plus, DOS-boxes (or whatever they should be called) are called by double-clicking, or used in a "clean" DOS box anyway ... it's not that we have 1 dos box, and that the whole OS is managed from withing that 1 box (like it was in the old days). THEN, I would consider it a potential threat, but otherwise, just be smart when naming variables.


ps : Can "EnableDelayedExpansion" not be used without SETLOCAL ?


Report •

#22
December 26, 2009 at 12:05:02
Yes, you're right about cmd being somewhat ephemeral, but i tend to spend a lot of session time in the same cmd window without exiting. sometimes i'll be running a test on a script, and i try to set, f/e, xx=!xx:~0,4! and it keeps coming back with "testing strings", then i look at env.table (SET) and see xx is persisting there with value "testing strings". THAT's what really bugs me.

i don't think "enabledelayedexpansion" is independant of "setlocal", it's more like an option of setlocal (see:
setlocal /? and endlocal /?) although there IS an option
disabledelayedexpansion that i've never seen used.


Report •

#23
December 27, 2009 at 05:16:00
Nothing prevents you from initialising variables, in the beginning of each script. It's good practice either ... and there is the whole clue : when you know this variable should only be used in this script (in this copy of the DOS box), it cannot harm to reset it .. unlike with PATH for example, you would never :

set PATH=

And the disabledelayedexpansion ... I'm learning that one as well, but it is disabling the optional feature enabledelayedexpansion ...

So,

setlocal disabledelayedexpansion

=

setlocal

??

Unless Windows decides to set "enabled" as default


Report •

#24
January 6, 2010 at 17:08:18
I think we got it. I will run it against windiff to take a look and test in development then. Sorry for the in testing this.

Thanks to all for your help this far.


Report •

#25
January 20, 2010 at 05:58:45
That did it. Thank you all for your dedication and hard work on this one.

Report •

Ask Question