Locate a keyword, replace string 3 lines down

August 13, 2010 at 08:42:37
Specs: Windows XP
I have been able to replace every instance of "old string" with "new string"in text file, however, I want to replace just a single instance of "old string".

I have tried this from Mechanxi2Go:

@echo off > newfile & setLocal enableDELAYedexpansion

set /p old=old string ?
set /p new=new string ?

for /f "tokens=* delims= " %%a in (myfile) do (
set str=%%a
set str=!str:%old%=%new%!
>> newfile echo !str!
)

This works to replace all instances of "old string" with "new string".

What I actually need it to locate a line, advance 3 lines, and replace a word in that line. I am not sure this is possible.

Circumstances:
1. I am modifying a tnsnames.ora file and the file I am modifying is different between computers.
2. The "new string" appears in several places within the file.
3. To isolate the line I need to modify, I would like to search for a keyword, which occurs once in the file.
4. The increment 3 lines to replace the "old string" with "new string"

Here is an excerpt of the file I am modifying:

IDB =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = firebird)(PORT = 1521))
)
(CONNECT_DATA =
(SID = idb)
)
)

IDB_FIREBIRD =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = firebird)(PORT = 1521))
)
(CONNECT_DATA =
(SID = idb)
)
)

In this excerpt, I am searching for "IDB =". I need to change the word "firebird" in the 3rd line down from located string.

I don't think this is possible, however, I'm hanging it out there to see if anyone can come up with something.

Oh, I'm also trying to do this in a batch file as there are different versions of Windows XP that I will be running this on. Also, not all machines have Windows Powershell installed. I also am not able to install additional software on the computers. I am open to suggestions using vbscript if it is easier, however, I am not versed in vbscript so I would ask for a complete solution in vbscript. Thanks!


See More: Locate a keyword, replace string 3 lines down

Report •

#1
August 13, 2010 at 09:42:20
:: find key line; modify 3rd line down
:: thrddown.bat  Fri 13-08-2010 23:24:02.71
@echo off > newfile & setLocal enableDELAYedeXpansion

for /f "tokens=1 delims=[]" %%a in ('find /n "IDB =" ^< thefile') do (
set L=%%a
)
set /a L+=3

set N=
for /f "tokens=* delims= " %%a in (thefile) do (
set /a N+=1
set S=%%a
  if !N! equ !L! (
    set S=!S:firebird=NEWSTRING!
  )
>> newfile echo.!S!
)


=====================================
Helping others achieve escape felicity

M2


Report •

#2
August 13, 2010 at 11:22:25
Okay, I have a few questions.

1. Is the variable %%a an input to the batch file?
2. I assume newfile is the output file to be renamed.
3. I'm not sure about "thefile". I think that is to be replaced with the actual input filename.
4. NEWSTRING is to be replaced with the string that is replacing the string of firebird.

When I modify the batch file with the following changes:
thefile is changed to tnsnames.ora
NEWSTRING is replaced with loki
I execute the batch file and it generates the newfile file, however, it does not have the firebird to loki change. I know I've misunderstood something here. Thanks.


Report •

#3
August 13, 2010 at 11:37:16
[1] No, it's geberated by the FOR loop.

[2 thru 4] You're correct.

Does your file to process have blank lines?


=====================================
Helping others achieve escape felicity

M2


Report •

Related Solutions

#4
August 13, 2010 at 11:42:43
Yes, there are blank lines in the file. Here is the excerpt:
IDB =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = firebird)(PORT = 1521))
)
(CONNECT_DATA =
(SID = idb)
)
)

IDB_FIREBIRD =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = firebird)(PORT = 1521))
)
(CONNECT_DATA =
(SID = idb)
)
)

Blank line between the groups, and spaces marking stanzas.


Report •

#5
August 13, 2010 at 11:45:23
Dang it, let me try this again...

.IDB =
. (DESCRIPTION =
. (ADDRESS_LIST =
. (ADDRESS = (PROTOCOL = TCP)(HOST = firebird)(PORT = 1521))
. )
. (CONNECT_DATA =
. (SID = idb)
. )
. )
.
.IDB_FIREBIRD =
. (DESCRIPTION =
. (ADDRESS_LIST =
. (ADDRESS = (PROTOCOL = TCP)(HOST = firebird)(PORT = 1521))
. )
. (CONNECT_DATA =
. (SID = idb)
. )
. )

(Ignore the periods at the beginning. I'm using them to format the text.) (I hope this works...)


Report •

#6
August 13, 2010 at 11:46:02
I guess I have to use HTML... Here it is again.

IDB =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = firebird)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SID = idb)
    )
  )

IDB_FIREBIRD =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = firebird)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SID = idb)
    )
  )


Report •

#7
August 13, 2010 at 11:59:08
You really got me now. [As the song says.]

I compared your #4 to orig; no diffs.

Then I created a file from your #6. It works.


=====================================
Helping others achieve escape felicity

M2


Report •

#8
August 13, 2010 at 12:14:51
Okay, I'm not sure what I am doing wrong then. Here is the batch file code:
:: find key line; modify 3rd line down
:: thrddown.bat  Fri 13-08-2010 23:24:02.71
@echo off
if exist tnsnames.new del tnsnames.new

@echo off > tnsnames.new & setLocal enableDELAYedeXpansion
if exist tnsnames.old del tnsnames.old

copy tnsnames.ora tnsnames.old

for /f "tokens=1 delims=[]" %%a in ('find /n "IDB =" ^< tnsnames.old') do (
set L=%%a
)
set /a L+=3

set N=
for /f "tokens=* delims= " %%a in (tnsnames.old) do (
set /a N+=1
set S=%%a
  if !N! equ !L! (
    set S=!S:firebird=NEWSTRING!
  )
>> tnsnames.new echo.!S!
)

::copy tnsnames.new tnsnames.ora.new
::del tnsnames.new
::del tnsnames.old

The output ends up like this:

IDB =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = firebird)(PORT = 1521))
)
(CONNECT_DATA =
(SID = idb)
)
)
IDB_FIREBIRD =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = firebird)(PORT = 1521))
)
(CONNECT_DATA =
(SID = idb)
)
)

There was no change in the first section of "HOST = firebird".


Report •

#9
August 13, 2010 at 12:30:26
With this bat:

==================================

:: find key line; modify 3rd line down
:: thrddown.bat  Fri 13-08-2010 23:24:02.71
@echo off
if exist tnsnames.new del tnsnames.new

@echo off > tnsnames.new & setLocal enableDELAYedeXpansion
if exist tnsnames.old del tnsnames.old

copy tnsnames.ora tnsnames.old

for /f "tokens=1 delims=[]" %%a in ('find /n "IDB =" ^< tnsnames.old') do (
set L=%%a
)
set /a L+=3

set N=
for /f "tokens=* delims= " %%a in (tnsnames.old) do (
set /a N+=1
set S=%%a
  if !N! equ !L! (
    set S=!S:firebird=NEWSTRING!
  )
>> tnsnames.new echo.!S!
)

::copy tnsnames.new tnsnames.ora.new
::del tnsnames.new
::del tnsnames.old

===============================

My tnsnames.new contains:
=============================

IDB =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = NEWSTRING)(PORT = 1521))
)
(CONNECT_DATA =
(SID = idb)
)
)
IDB_FIREBIRD =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = firebird)(PORT = 1521))
)
(CONNECT_DATA =
(SID = idb)
)
)


=====================================
Helping others achieve escape felicity

M2


Report •

#10
August 13, 2010 at 12:50:16
I think I know what the problem is. I didn't actually see it until just now it's in the line:
  if !N! equ !L! (

I have, for what ever reason, problems with the ne, equ, portions of the if/then statements, and I don't know why. I have run into this in the past. The command interperter is version Microsoft Windows XP [Version 5.1.2600]. I'll check this on Monday as I need to leave the office for today.

I'll keep working on this though. Thank your for your assistance.


Report •

#11
August 13, 2010 at 12:57:20
Let us know.


=====================================
Helping others achieve escape felicity

M2


Report •

#12
August 16, 2010 at 09:56:01
I think I have found the crux of my problem. Apparently, SETLOCAL can only be used to set either enabledelayedexpansion or enableextensions. Not both. To use equ, in the IF/THEN statement, I need enableextensions set. Hmm... I'm still working on this.

EDIT: Well, it looks like I am going to end up going with awk. Seems to be the easiest way to do this. Thanks for all the help M2!


Report •

Ask Question