Page 1 of 1

Problem with BatchSubstitute.bat

Posted: 18 Dec 2009 05:55
by rafaelbc
Hello,

I found BatchSubstitute.bat really useful, but then I started having problems when the file contained information like the example below:
hey, "this is a example & test file", ain't it?

If the file contains a line with a '&' between double quotes, I get errors like:
'test' is not recognized as an internal or external command, operable program or batch file.
'hey' is not recognized as an internal or external command, operable program or batch file.

Any hints on how I could have that problems fixed?

Thanks in advance!

Posted: 18 Dec 2009 15:53
by avery_larry
Well, since the "&" symbol is a special character, one obvious (and frankly preferred) solution is to mofidy the code and replace "&" with "and" wherever appropriate.

If you must use the & symbol, you can try to escape it with a ^


hey, "this is a example ^& test file", ain't it?

However, from the error output you show, I'm expecting that you need that line to be either ECHO or REM:

rem hey, "this is a example & test file", ain't it?

Posted: 21 Dec 2009 04:44
by rafaelbc
BatchSubstitute.bat is one of the batch files provided by DosTips, so that is the error that is output to me when I run it - I have no special needs for ECHOing or REMing.

When I enter:
$ BatchSubstitute.bat a b test.txt

Where test.txt contains that string, I get those errors.

I appreciate the answer, however I have no chance for manually replacing '&' for 'and' or '^&', since the files I'm working with are provided by someone else (the string I used was merely an example).

Any ideas about what I could do?

Posted: 22 Dec 2009 00:38
by DosItHelp
The batch file described at http://www.dostips.com/DtCodeBatchFiles.php#Batch.FindAndReplace has limitations. If the text file to be searched/replaced contains on of the characters &|<> in a line without being quoted then the batch will not process this line correctly. (A proper note has been added to the post.)

The following script acts opposite. It only works if the special characters &|<> are quoted if they appear (rafaelbc this may help in your case):

Code: Select all

@echo off
REM -- Prepare the Command Processor --
SETLOCAL ENABLEEXTENSIONS
SETLOCAL DISABLEDELAYEDEXPANSION

::BatchSubstitude - parses a File line by line and replaces a substring"
::syntax: BatchSubstitude.bat OldStr NewStr File
::          OldStr [in] - string to be replaced
::          NewStr [in] - string to replace with
::          File   [in] - file to be parsed
if "%*"=="" findstr "^::" "%~f0"&GOTO:EOF
for /f "tokens=1* delims=]" %%A in ('type %3^|find /n /v ""') do (
    set "line=%%B"
    if defined line (
        call echo.%%line:%~1=%~2%%
    ) else (echo.)
)

Output:
C:\>type BatchSubstitute.txt
!!! THIS TEST DOESN`T REPLACE ANYTHING, IT JUST CHECKS MAKES SURE
!!! THE SCRIPT WORKS FOR SPECIAL CHARACTERS
!!! THE SCRIPT DOESN'T WORK CORRECTLY IF ANY OF THE CHARACTERs "&|^"
!!! APPEAR IN A LINE WITHOUT BEING QUOTED.
Next line is empty

this ( is a opening bracket character
this ) is a closing bracket character
this % is a percent character
this ! is an exclamation character
this " is a quote character
this > is a grater-than character
this < is a less-than character
this & is an ampersand character
this | is a vertical character
this ^ is a up character

this is a "quoted string"
this is a %percented string%
this is a !exclamationed string!
a "quoted ( opening bracket"
a "quoted ) closing bracket"
a "quoted % quote character"
a "quoted ! quote character"
a "quoted " quote character"
a "quoted > grater-than bracket"
a "quoted < less-than bracket"
a "quoted & ampersand"
a "quoted | vertical"
a "quoted ^ up character"

C:\>BatchSubstitute2.bat Oldtext Newtext BatchSubstitute.txt
!!! THIS TEST DOESN`T REPLACE ANYTHING, IT JUST CHECKS MAKES SURE
!!! THE SCRIPT WORKS FOR SPECIAL CHARACTERS
!!! THE SCRIPT DOESN'T WORK CORRECTLY IF ANY OF THE CHARACTERs "&|^"
!!! APPEAR IN A LINE WITHOUT BEING QUOTED.
Next line is empty

this ( is a opening bracket character
this ) is a closing bracket character
this % is a percent character
this ! is an exclamation character
this " is a quote character
this a grater-than character
this a less-than character
this is a up character

this is a "quoted string"
this is a %percented string%
this is a !exclamationed string!
a "quoted ( opening bracket"
a "quoted ) closing bracket"
a "quoted % quote character"
a "quoted ! quote character"
a "quoted " quote character"
a "quoted > grater-than bracket"
a "quoted < less-than bracket"
a "quoted & ampersand"
a "quoted | vertical"
a "quoted ^ up character"

If however you have a mixed case, where sometimes the special character &|<> appear within quotes and not within quotes, then there seems to be no clean batch file solution for a search and replace.

Re: Problem with BatchSubstitute.bat

Posted: 22 Dec 2009 02:55
by ghostmachine4
rafaelbc wrote:Any hints on how I could have that problems fixed?

do yourself a favour and use something better than batch for parsing/replacing text. you can use vbscript if you are the native guy, or you can use good string parsing/replacement tools like sed/gawk. here's an example with vbscript

Code: Select all

Set objFS=CreateObject("Scripting.FileSystemObject")
strOld = WScript.Arguments.Item(0)
strNew = WScript.Arguments.Item(1)
strFile = WScript.Arguments.Item(2)
Set objFile = objFS.OpenTextFile(strFile)
Do Until objFile.AtEndOfStream
   strLine = objFile.ReadLine
   WScript.Echo Replace(strLine,strOld,strNew)
Loop


Save the above as replace.vbs and on the command line

Code: Select all


C:\test>type file
this is a line with ampersand &
the && "" text i want " to change is this word called "test"
this is the end line with quotes " " " "

C:\test>cscript //nologo test.vbs test newword file
this is a line with ampersand &
the && "" text i want " to change is this word called "newword"
this is the end line with quotes " " " "


No worries about & or " messing up.
you can save to another file using the redirection > operator.

Posted: 22 Dec 2009 23:28
by DosItHelp
Good point ghostmachine4.
To make it transparent to batch users here a batch function that creates the vb script on the fly and uses it.

Code: Select all

@echo off
::BatchSubstitude - parses a File line by line and replaces a substring"
::syntax: BatchSubstitude.bat OldStr NewStr File
::          OldStr [in] - string to be replaced
::          NewStr [in] - string to replace with
::          File   [in] - file to be parsed
if "%*"=="" findstr "^::" "%~f0"&GOTO:EOF
call:replaceInFile %*
goto:eof


::--------------------------------------------------------
::-- Function section starts below here
::--------------------------------------------------------


:replaceInFile oldText newText file -- replaces a string in a text file
::                                  -- OldStr [in] - string to be replaced
::                                  -- NewStr [in] - string to replace with
::                                  -- File   [in] - file to be parsed:$created 20091222 :$changed 20091222 :$categories FileOperation,VB
:$source http://www.dostips.com
Setlocal Disabledelayedexpansion
set "fn=%0"
set "fn=%fn:~1%.vbs"
md "%temp%.\dostips.com\" >NUL 2>&1
REM the xcopy helps checking if the vbs file needs to be created or re-created
xcopy /diyl "%~f0?" "%temp%.\dostips.com\%fn%"|find "1 File(s)">NUL&&(
    set "cpy="
    (for /f "tokens=1* delims=]" %%A in ('find /v /n "" "%~f0"') do (
        if "%%B"=="'%fn%" set "cpy=Y"
        if "%%B"=="EXIT /b" set "cpy="
        if defined cpy call echo.%%B
    ))>"%temp%.\dostips.com\%fn%"
    REM echo.Updated:"%temp%.\dostips.com\%fn%"
)
cscript //nologo "%temp%.\dostips.com\%fn%" %*
exit /b
'replaceInFile.vbs
'$created 20091222 '$changed 20091222
'$source http://www.dostips.com
'$creatorbatch %~f0,%date%,%time%
Set objFS=CreateObject("Scripting.FileSystemObject")
strOld = WScript.Arguments.Item(0)
strNew = WScript.Arguments.Item(1)
strFile = WScript.Arguments.Item(2)
Set objFile = objFS.OpenTextFile(strFile)
Do Until objFile.AtEndOfStream
   strLine = objFile.ReadLine
   WScript.Echo Replace(strLine,strOld,strNew)
Loop
EXIT /b

Posted: 23 Dec 2009 00:23
by ghostmachine4
i think hybrids should be avoided as far as possible. I recommend just using vbscript, since vbscript can do most of the thing batch does and code is cleaner and easier to read and debug.

Re: Problem with BatchSubstitute.bat

Posted: 29 Dec 2010 06:40
by drocks
I also found the BatchSubstitute.bat really useful - Thank you.

Is there a way it can be modified to except regular expressions, such as /.*$ (to get all from a / to the end of the line)? I have tried modifying BatchSubstitute.bat for findstr /R, but I break it each time I touch it (i'm sort of new at this). If Dos batch is not correct, a vbs would do as well -

Amy help would be much appreciated!!

Re: Problem with BatchSubstitute.bat

Posted: 29 Dec 2010 08:45
by aGerman
Yeah I think VBScript is a better way to handle regex patterns, but vbs is kinda off topic in this forum. How ever, have a look at the msdn. It shows how to do.

Regards
aGerman

Re: Problem with BatchSubstitute.bat

Posted: 29 Dec 2010 09:40
by ghostmachine4
drocks wrote:I also found the BatchSubstitute.bat really useful - Thank you.

Is there a way it can be modified to except regular expressions, such as /.*$ (to get all from a / to the end of the line)? I have tried modifying BatchSubstitute.bat for findstr /R, but I break it each time I touch it (i'm sort of new at this). If Dos batch is not correct, a vbs would do as well -

Amy help would be much appreciated!!


again, if you want a native solution, vbscript or powershell is the way to go. Otherwise, if you can use tools, download GNU sed or gawk for windows, which are good at parsing and doing things to text/strings, especially using regex.

Re: Problem with BatchSubstitute.bat

Posted: 29 Dec 2010 13:21
by drocks
Thank you very much for this. It looks like vbs is the way to go. With the help of the sight you mentioned I found an example of a vb script which almost does exactly what I need (pasted below - you will probably recognize it, except that I pasted in /.*$ in the search expression). But I can't quite figure out the syntax to replace the strings which resulted from the search. In other words, I want to replace all the text found with /.*$ with a blank. In the example below, they are replacing the text "PT" with "" (a blank) for any lines which contain /.*$. I need to somehow replace the expression "PT" to be that of the results of the search. Any thoughts on where I could find the correct expressions to do that?


Const ForReading = 1
Const ForWriting = 2

Set fso = CreateObject("Scripting.FileSystemObject")
Set objRE = CreateObject("VBScript.RegExp")
objRE.Global = True
objRE.IgnoreCase = False
objRE.Pattern = "/.*$"

Set inFile = fso.OpenTextFile("c:\temp\file.txt", ForReading)
Set outFile = fso.OpenTextFile("c:\temp\file.chg", ForWriting, True)

Do Until inFile.AtEndOfStream
strLine = inFile.ReadLine
Set colMatches = objRE.Execute(strLine)
If colMatches.Count > 0 Then
strLine = Replace(strLine, "PT "")
End If
outFile.WriteLine strLine
Loop

Re: Problem with BatchSubstitute.bat

Posted: 29 Dec 2010 15:38
by aGerman

Code: Select all

strLine = Replace(strLine, "PT", "")

Otherwise give an example line and show what you try to do.

Regards
aGerman

Re: Problem with BatchSubstitute.bat

Posted: 30 Dec 2010 10:45
by drocks
Thank you, I appreciate the response. I ended up getting lucky and found exactly what I needed at the site (http://www.computerhope.com/forum/index ... 02.15.html) from user Sidewinder. I did not want to post his work here, better going to the source - but is it a great solution to what I was looking for.

Thanks again!