I have search over SO but cant find similar topic so I have decided to write one. I would like to have a command in my Windows batch file .bat that can replace content of 1 or more files with wildcard masks. For example:
replace *.txt "searchin? str?ng*" "replacing string"
Can someone let me know if that is possible?
Many Thanks,
Windows does not have a native command line tool (except for perhaps PowerShell) that can do this. But there are Windows ports of unix utilities like sed that could do the job well. Any utility that supports regular expression search and replace would work well, though the syntax for wildcards is not what you have in your example. Regular expressions are extremely powerful, and you will want to read some tutorials on how to use them. There are many tutorials available on the web.
I have written a hybrid JScript/batch utility called REPL.BAT that performs a regular expression search/replace on stdin and writes the result to stdout. The utility is pure script that will run natively on any modern Windows machine from XP onward. Full documentation is embedded within the script.
Using REPL.BAT, your example could be implemented as:
#echo off
for %%F in (*.txt) do (
type "%%F" | repl "searchin. str.ng.*" "replacing string" >"%%F.new"
move /Y "%%F.new" "%%F"
)
Note that ? (any 1 character) in your question is expressed as . in a regular expression, and * (any 0 or more characters) is expressed as .*.
The above could easily be converted into a general purpose REPLACE.BAT "command".
#echo off
for %%F in (%1) do (
type "%%F" | repl %2 %3 >"%%F.new"
move /Y "%%F.new" "%%F"
)
Then the above would be called using:
replace *.txt "searchin. str.ng.*" "replacing string"
This assumes that both REPL.BAT and REPLACE.BAT are either in your current directory, or else somewhere within your PATH.
This is a vbs program.
ReplaceRegEx.vbs Filename SearchString [ReplaceString]
This is the code.
On Error Resume Next
Set ShellApp = CreateObject("Shell.Application")
ReportErrors "Creating Shell.App"
set WshShell = WScript.CreateObject("WScript.Shell")
ReportErrors "Creating Wscript.Shell"
Set objArgs = WScript.Arguments
ReportErrors "Creating Wscript.Arg"
Set regEx = New RegExp
ReportErrors "Creating RegEx"
Set fso = CreateObject("Scripting.FileSystemObject")
ReportErrors "Creating FSO"
If objArgs.Count = 0 then
MsgBox "No parameters", 16, "Serenity's ReplaceRegExp"
ReportErrors "Help"
ElseIf objArgs.Count = 1 then
MsgBox "Only one parameter", 16, "Serenity's ReplaceRegExp"
ReportErrors "Help"
ElseIf objArgs.Count = 2 then
Set srcfile = fso.GetFile(objArgs(0))
ReportErrors "srcFile"
If err.number = 0 then Set TS = srcFile.OpenAsTextStream(1, 0)
If err.number <> 0 then
Msgbox err.description & " " & srcFile.path, 48, "Serenity's Search"
err.clear
else
ReportErrors "TS" & " " & srcFile.path
Src=ts.readall
If err.number = 62 then
err.clear
else
ReportErrors "ReadTS" & " " & srcFile.path
regEx.Pattern = objArgs(1)
regEx.IgnoreCase = True
regEx.Global = True
If regEx.Test(Src) = True then
Msgbox "Found in " & srcfile.path, 64, "Serenity's Search"
End If
End If
End If
ReportErrors "Check OK" & " " & srcFile.path
Elseif objArgs.count = 3 then
Set srcfile = fso.GetFile(objArgs(0))
ReportErrors "srcFile"
If err.number = 0 then Set TS = srcFile.OpenAsTextStream(1, 0)
If err.number <> 0 then
Msgbox err.description & " " & srcFile.path, 48, "Serenity's Search"
err.clear
else
ReportErrors "TS" & " " & srcFile.path
Src=ts.readall
If err.number = 62 then
err.clear
else
ReportErrors "ReadTS" & " " & srcFile.path
regEx.Pattern = objArgs(1)
regEx.IgnoreCase = True
regEx.Global = True
NewSrc= regEx.Replace(Src, objArgs(2))
If NewSrc<>Src then
Msgbox "Replacement made in " & srcfile.path, 64, "Serenity's Search"
TS.close
Set TS = srcFile.OpenAsTextStream(2, 0)
ts.write newsrc
ReportErrors "Writing file"
End If
End If
End If
ReportErrors "Check OK" & " " & srcFile.path
Else
MsgBox "Too many parameters", 16, "Serenity's ReplaceRegExp"
ReportErrors "Help"
ReportErrors "All Others"
End If
Sub ReportErrors(strModuleName)
If err.number<>0 then Msgbox "An unexpected error occurred. This dialog provides details on the error." & vbCRLF & vbCRLF & "Error Details " & vbCRLF & vbCRLF & "Script Name" & vbTab & Wscript.ScriptFullName & vbCRLF & "Module" & vbtab & vbTab & strModuleName & vbCRLF & "Error Number" & vbTab & err.number & vbCRLF & "Description" & vbTab & err.description, vbCritical + vbOKOnly, "Something unexpected"
Err.clear
End Sub
These are the rules.
Special characters and sequences are used in writing patterns for regular expressions. The following table describes and gives an example of the characters and sequences that can be used.
Character Description
\
Marks the next character as either a special character or a literal. For example, "n" matches the character "n". "\n" matches a newline character. The sequence "\\" matches "\" and "\(" matches "(".
^
Matches the beginning of input.
$
Matches the end of input.
*
Matches the preceding character zero or more times. For example, "zo*" matches either "z" or "zoo".
+
Matches the preceding character one or more times. For example, "zo+" matches "zoo" but not "z".
?
Matches the preceding character zero or one time. For example, "a?ve?" matches the "ve" in "never".
.
Matches any single character except a newline character.
(pattern)
Matches pattern and remembers the match. The matched substring can be retrieved from the resulting Matches collection, using Item [0]...[n]. To match parentheses characters ( ), use "\(" or "\)".
x|y
Matches either x or y. For example, "z|wood" matches "z" or "wood". "(z|w)oo" matches "zoo" or "wood".
{n}
n is a nonnegative integer. Matches exactly n times. For example, "o{2}" does not match the "o" in "Bob," but matches the first two o's in "foooood".
{n,}
n is a nonnegative integer. Matches at least n times. For example, "o{2,}" does not match the "o" in "Bob" and matches all the o's in "foooood." "o{1,}" is equivalent to "o+". "o{0,}" is equivalent to "o*".
{ n , m }
m and n are nonnegative integers. Matches at least n and at most m times. For example, "o{1,3}" matches the first three o's in "fooooood." "o{0,1}" is equivalent to "o?".
[ xyz ]
A character set. Matches any one of the enclosed characters. For example, "[abc]" matches the "a" in "plain".
[^ xyz ]
A negative character set. Matches any character not enclosed. For example, "[^abc]" matches the "p" in "plain".
[ a-z ]
A range of characters. Matches any character in the specified range. For example, "[a-z]" matches any lowercase alphabetic character in the range "a" through "z".
[^ m-z ]
A negative range characters. Matches any character not in the specified range. For example, "[m-z]" matches any character not in the range "m" through "z".
\b
Matches a word boundary, that is, the position between a word and a space. For example, "er\b" matches the "er" in "never" but not the "er" in "verb".
\B
Matches a non-word boundary. "ea*r\B" matches the "ear" in "never early".
\d
Matches a digit character. Equivalent to [0-9].
\D
Matches a non-digit character. Equivalent to [^0-9].
\f
Matches a form-feed character.
\n
Matches a newline character.
\r
Matches a carriage return character.
\s
Matches any white space including space, tab, form-feed, etc. Equivalent to "[ \f\n\r\t\v]".
\S
Matches any nonwhite space character. Equivalent to "[^ \f\n\r\t\v]".
\t
Matches a tab character.
\v
Matches a vertical tab character.
\w
Matches any word character including underscore. Equivalent to "[A-Za-z0-9_]".
\W
Matches any non-word character. Equivalent to "[^A-Za-z0-9_]".
\num
Matches num, where num is a positive integer. A reference back to remembered matches. For example, "(.)\1" matches two consecutive identical characters.
\ n
Matches n, where n is an octal escape value. Octal escape values must be 1, 2, or 3 digits long. For example, "\11" and "\011" both match a tab character. "\0011" is the equivalent of "\001" & "1". Octal escape values must not exceed 256. If they do, only the first two digits comprise the expression. Allows ASCII codes to be used in regular expressions.
\xn
Matches n, where n is a hexadecimal escape value. Hexadecimal escape values must be exactly two digits long. For example, "\x41" matches "A". "\x041" is equivalent to "\x04" & "1". Allows ASCII codes to be used in regular expressions.
Related
I have a set of strings that may or may not have special characters in it.
Example:
Windows Live Fot¢t r
Galer¡a fotogr fica de Windows Live
Windows Live Maker
What i wanna do is to:
check whether the whole string contains a special character in it
If yes, replace these characters with a "?"
I haven't tried anything yet since i'm a newbie in vb scripting.
You can use a regular expression where you add every character that you consider as a non-special character.
stringsToCheck = Array("Windows Live Fot¢t r", _
"Galer¡a fotogr fica de Windows Live", _
"Windows Live Maker")
Set regExp = New RegExp
regExp.IgnoreCase = True
regExp.Global = True
regExp.Pattern = "[^a-z0-9 !?#]" 'Add here every character you don't consider as special character
For each str In stringsToCheck
strProcessed = regExp.Replace(str, "?")
WScript.Echo "Old String: " & str
WScript.Echo "New String: " & strProcessed
Next
Output:
Old String: Windows Live Fot¢t r
New String: Windows Live Fot?t r
Old String: Galer¡a fotogr fica de Windows Live
New String: Galer?a fotogr fica de Windows Live
Old String: Windows Live Maker
New String: Windows Live Maker
You can try below code ..
Function replaceChars(str As String) As String
'msgbox replacechars ("!##$%^&*(") will return !#$%^&()
Dim elem As Variant
replaceChars = str
For Each elem In Array("/", "\", ":", "*", "?", "<", ">", "|", "#", Chr(34))
replaceChars = Replace(replaceChars, elem, "?")
Next
End Function
Try something like this:
strCur="!##$%^&*()?><~`+=|\/.',{}[];:-%_20"
for iCount = 0 to len(strCur )
paragraph= Replace(paragraph, Mid(strCur, iCount + 1, 1), "?")
next
'This line should replace those characters. You'll need a line for each char.
paragraph = Replace$(paragraph, Chr(123), "a")
paragraph = Replace$(paragraph, Chr(173), "A")
I am trying to understand something about about the way VBS splits single lines of code across multiple lines.
In the below function the _ character is used in two places to split execution across two lines, ok all fine.
For Each objItem in colItems
if i=0 then
header = ""
For Each param in objItem.Properties_
header = header & param.Name & vbTab
Next
WScript.Echo header
i=1
end if
serviceData = ""
For Each param in objItem.Properties_
serviceData = serviceData & param.Value & vbTab
Next
WScript.Echo serviceData
Next
What I do not understand then is how this is supposed to look on a single line. When I modify either of the lines with any of the below I get an error.
For Each param in objItem.Propertiesheader = header & param.Name & vbTab
For Each param in objItem.Properties.header = header & param.Name & vbTab
For Each param in objItem.Properties header = header & param.Name & vbTab
Errors to the effect of:
C:\Program Files (x86)\ManageEngine\AppManager12\working\conf\application\scripts\wmiget.vbs(86,2) Microsoft VBScript runtime error: Object doesn't support this property or method: 'objItem.PropertiesserviceData'
How would the above be correctly represented on a single line?
The issue here is you are using the Line Continuation Character _ to continue a line when it isn't required.
You only use it if you need a single line of code to span multiple lines, using your example something like;
For Each _
param _
in _
objItem.Properties
serviceData = serviceData & param.Value & vbTab
Next
will work (be it a bit pointless) because the single line
For Each param in objItem.Properties
is being spanned across multiple lines.
So, because the line;
For Each param in objItem.Properties
is a single line of code no continuation is required as the next line of code is expected. However, when you provide it, it causes VBScript to error with;
Microsoft VBScript compilation error: Expected end of statement
Which is VBScript's way of telling you that the line isn't finished and still expects the end of the code statement.
If you do want to span multiple code statements across a single line use colon (:) which acts as a statement seperator, i.e;
For Each param in objItem.Properties : serviceData = serviceData & param.Value & vbTab : Next
Useful Links
Line Continuation Character (_) also known as a Statement Break.
Breaking a String Across Multiple Lines (Focuses on strings but talks about the Line Continuation Character).
VBScript, purpose of colon?
I am trying to implement search whole word only in VBScript, I tried appeding characters like space, /, ],) etc. as these characters means end of word. I need to do as many search as the number of characters I want to include using or operator. Is there any way to do it easily in VBScript.
Currently I am doing :-
w_seachString =
searchString & " " or
searchString & "/" or
searchString & "]" or
searchString & ")" or
searchString & "}" or
searchString & "," or
searchString & "."
So eventually I am comparing with lots of combination and looking for an effective way to make my variable w_seachString able to search for whole word only.
Use a regular expression with a word boundary anchor. Demo:
Option Explicit
Function qq(s) : qq = """" & s & """" : End Function
Dim r : Set r = New RegExp
r.Pattern = "\bx\b"
Dim s
For Each s In Split("axb| x |ax|x|\x/|", "|")
WScript.Echo qq(s), CStr(r.Test(s))
Next
output:
cscript 36443611.vbs
"axb" False
" x " True
"ax" False
"x" True
"\x/" True
"" False
By some google resources I could write a program to extract the string between two specific strings. I could not print value or store the value into a variable using regular expressions. Here is my code.
prgName = InStr(vText, "Program")
sub_prgName = Mid(vText, prgName, 100)
MsgBox sub_prgName, vbInformation
Dim RegEx: Set RegEx = New RegExp
RegEx.IgnoreCase = True
RegEx.Pattern = "Program(.*)?Variant"
Set RegEx = RegEx.Execute(prgName)
MsgBox RegEx.Value, vbInformation
I want to get the string b/w Program and Variant. When try to see the output it says
Run time error 438, object doesn't support this property.
This is the value that I want to parse using RegEx:
Program
sqlplus $SOPS_MIPO_USER/$SOPS_MIPO_PASSWORD#$DB_SID #mipo_pruning.sql
Variant
When in doubt, read the documentation. The Execute method returns a Matches collection, so you need to iterate over that collection to get the desired result (in your case the first submatch).
For Each m In RegEx.Execute(prgName)
MsgBox m.SubMatches(0), vbInformation
Next
Demonstration:
>>> s = "Program sqlplus $SOPS_MIPO_USER/$SOPS_MIPO_PASSWORD#$DB_SID #mipo_pruning.sql Variant N/A"
>>> Set re = New RegExp
>>> re.Pattern = "Program(.*)?Variant"
>>> re.IgnoreCase = True
>>> For Each m In re.Execute(s) : WScript.Echo m.SubMatches(0) : Next
sqlplus $SOPS_MIPO_USER/$SOPS_MIPO_PASSWORD#$DB_SID #mipo_pruning.sql
Theoretically you could also do this without the loop:
Set m = RegEx.Execute(prgName)(0)
MsgBox m.SubMatches(0), vbInformation
However, RegEx.Execute(prgName)(0) would raise an error if the regular expression didn't find a match, so evaluating the results in a loop is the safer approach.
I'd remove the ? in your regular expression, though, because it'll make the group optional, so you're not guaranteed to have a SubMatches(0) item. Simply use Program(.*)Variant instead. If there's no text between "Program" and "Variant" you'll get a zero-length string as the first submatch. Or you could put it inside the parentheses right after the asterisk (Program(.*?)Variant) to make the match non-greedy (shortest match instead of longest match).
If your input string contains newlines you need to use [\s\S] instead of ., because the dot in regular expressions matches any character except newlines.
Demonstration:
>>> s = "Program" & vbNewLine & vbNewLine _
& "sqlplus $SOPS_MIPO_USER/$SOPS_MIPO_PASSWORD#$DB_SID #mipo_pruning.sql" _
& vbNewLine & vbNewLine & "Variant"
>>> WScript.Echo s
Program
sqlplus $SOPS_MIPO_USER/$SOPS_MIPO_PASSWORD#$DB_SID #mipo_pruning.sql
Variant
>>> Set re = New RegExp
>>> re.Pattern = "Program(.*)?Variant"
>>> re.IgnoreCase = True
>>> For Each m In re.Execute(s) : WScript.Echo m.SubMatches(0) : Next
>>> re.Pattern = "Program([\s\S]*)?Variant"
>>> For Each m In re.Execute(s) : WScript.Echo m.SubMatches(0) : Next
sqlplus $SOPS_MIPO_USER/$SOPS_MIPO_PASSWORD#$DB_SID #mipo_pruning.sql
As a side note, you shouldn't replace your regular expression object with the result of the Execute method.
Set RegEx = RegEx.Execute(prgName) '<-- NEVER do this!
Re-using variables is a no-no, so don't do it.
.Execute returns a collection of Match objects. This collection has a .Count but no .Value property. You can use MsgBox RegEx(0).Value to get the .Value of the first match.
Evidence:
>> sInp = "XXXProgramYYYVariantZZZ"
>> Set r = New RegExp
>> r.Pattern = "Program(.*?)Variant"
>> WScript.Echo r.Execute(sInp)(0).Value
>> WScript.Echo r.Execute(sInp)(0).SubMatches(0)
>>
ProgramYYYVariant
YYY
You should publish your input(s) and expected result(s).
Please how to pass the 'inp" variable from this piece of vbs to my batch named job.bat? Indeed when doing echoing (echo %2) from job.bat, i notice that the inp is not passed properly. prompt command views inp and not the value retrieved from vbs. Thanks
For Each listElement In xmlDoc.selectNodes("document/Lists/list")
msgbox "toto"
inp=listElement.selectSingleNode("entry").text
out= listElement.selectSingleNode("output").text
jeton= listElement.selectSingleNode("token").text
dim shell
set shell=createobject("wscript.shell")
shell.run "job.bat ""a file"" **inp** "
set shell=nothing
Next
I think what you're looking for is this.
shell.run "job.bat ""argfile.ext"" " & inp
However, as Ansgar Wiechers points out, this is a potentially severe security hole, as a treacherously crafted XML file could run arbitrary commands. To encapsulate your batch file arguments and prevent unintended consequences, consider switching to the Shell.Application object's ShellExecute method.
For Each listElement In xmlDoc.selectNodes("document/Lists/list")
msgbox "toto"
inp = listElement.selectSingleNode("entry").text
out = listElement.selectSingleNode("output").text
jeton = listElement.selectSingleNode("token").text
set shell=CreateObject("Shell.Application")
shell.ShellExecute "job.bat", """a file"" " & inp, "path\to\batfile\", "runas", 1
set shell=nothing
Next
Unlike several other languages VBScript doesn't expand variables inside strings. Because of that, inp in the string
"job.bat ""a file"" inp "
is just the literal string "inp", not the value of the variable inp. To produce a string with the value of a variable, you have to concatenate base string and variable like #rojo suggested:
shell.run "job.bat ""a file"" " & inp
I would, however, not recommend doing this without some safety precautions. For one thing you should always put double quotes around your arguments, in case they contain spaces. I normally use a quoting function for this to prevent the instruction from becoming riddled with quad-quotes:
Function qq(str) : qq = Chr(34) & str & Chr(34) : End Function
'...
shell.run "job.bat " & qq("a file") & " " & qq(inp)
You should also always apply sanitizing to all user input that is passed to a shell command. Otherwise your users might wreak havoc by entering something like foo & del /s /q C:\*.*. Common practice is to allow only known-good characters in the input string and replace everything else with a safe character (e.g. an underscore). You can achieve this with a regular expression:
Set re = New RegExp
re.Pattern = "[^ a-z0-9äöü.,_$%()-]"
re.Global = True
re.IgnoreCase = True
inp = re.Replace(inp, "_")