I have a set of data like this
7859 10000:00 7859 10000:00 (xfer#1, to-check=1033/1035)
32768 000:17 22174479 10000:00 (xfer#2, to-check=1032/1035)
They are read from a file and passed line by line to a method inside my batch script
What I want to do in that method is to extract only
7859
22174479
from this lines, basically whatever is after "\d+:\d\d\s+", then what follows are the numbers that I need and then another "\d\d.*"
Is this possible using only batch script regular expression and search and replace?
I tried and read a bunch of articles but could not find a solution
In the and I want to add the numbers
Thank you
EDIT
Based on Andrei's comment to David Ruhmann's answer, Andrei wants the token that is 2 positions before (xfer#, not the 3rd token from the beginning.
Do note that batch is not the best language to use for regex! Cmd processes the input one line at a time, whereas regex allows for multi-line processing.
It sounds like you just need to perform a token grab from the lines. Assuming the more complete regex for the line looks like this [\d+\s+\d+:\d\d\s+]+\(xfer#\d+, to-check=\d+/\d+\).
This allows us to know that there are constant delimiters in the line. : colons, and \s+ whitespace. From there it is just a matter of using those anchors to determine the token position.
Extract the third token delimited by single line whitespace from the line.
for /f "tokens=3" %%A in ("line") do echo %%A
Extract the second token delimited by single line whitespace from the second token delimited by colons from the line.
for /f "tokens=2 delims=:" %%A in ("line") do (
for /f "tokens=2" %%B in ("%%A") do echo %%B
)
Update
Extract the second token before the last colon.
#echo off
setlocal EnableExtensions EnableDelayedExpansion
set "Line=32768 004:47 2686976 2200:03 11707819 10000:01 (xfer#5264, to-check=1020/6975)"
set "Last="
for /f "delims=" %%A in ('echo("%Line::="^&echo("%"') do (
for /f "tokens=2" %%B in ("%%A") do (
if defined This set "Last=!This!"
set "This=%%B"
)
)
echo %Last%
endlocal
pause >nul
Limitations
Lines containing an odd number of double quotation marks " will cause the script to crash. One method to prevent this is to strip out the quotations before the for loop with set Line=%Line:"=%.
Based on your comment to David Ruhmann's answer, you want the token that is 2 positions before the (xfer# string. I suppose it can be done using native batch commands, but that is a nasty problem.
I am assuming you are restricted to commands that are native to Windows - no downloaded executables.
I'm hoping that you may use JScript, since it is native to Windows.
I have written a hybrid JScript/Batch utility script named "REPL.BAT" that performs regex search and replace. It is an amazingly useful utility, despite not requiring much code. The utility makes the solution very simple.
I use FINDSTR to filter out the lines that don't meet the template of at least 2 space delimted tokens prior to (xfer#. I pipe those results to my REPL utility and preserve only the desired token. The result is sent to stdout.
findstr /r /c:" [^ ][^ ]* [^ ][^ ]* (xfer#" test.txt | repl ".* ([^ ]+) ([^ ]+) \(xfer#.*" "$1"
Here is the code for the REPL.BAT utility script. Full documentation is embedded within the script.
#if (#X)==(#Y) #end /* Harmless hybrid line that begins a JScript comment
::************ Documentation ***********
:::
:::REPL Search Replace [Options [SourceVar]]
:::REPL /?
:::
::: Performs a global search and replace operation on each line of input from
::: stdin and prints the result to stdout.
:::
::: Each parameter may be optionally enclosed by double quotes. The double
::: quotes are not considered part of the argument. The quotes are required
::: if the parameter contains a batch token delimiter like space, tab, comma,
::: semicolon. The quotes should also be used if the argument contains a
::: batch special character like &, |, etc. so that the special character
::: does not need to be escaped with ^.
:::
::: If called with a single argument of /? then prints help documentation
::: to stdout.
:::
::: Search - By default this is a case sensitive JScript (ECMA) regular
::: expression expressed as a string.
:::
::: JScript syntax documentation is available at
::: http://msdn.microsoft.com/en-us/library/ae5bf541(v=vs.80).aspx
:::
::: Replace - By default this is the string to be used as a replacement for
::: each found search expression. Full support is provided for
::: substituion patterns available to the JScript replace method.
::: A $ literal can be escaped as $$. An empty replacement string
::: must be represented as "".
:::
::: Replace substitution pattern syntax is documented at
::: http://msdn.microsoft.com/en-US/library/efy6s3e6(v=vs.80).aspx
:::
::: Options - An optional string of characters used to alter the behavior
::: of REPL. The option characters are case insensitive, and may
::: appear in any order.
:::
::: I - Makes the search case-insensitive.
:::
::: L - The Search is treated as a string literal instead of a
::: regular expression. Also, all $ found in Replace are
::: treated as $ literals.
:::
::: E - Search and Replace represent the name of environment
::: variables that contain the respective values. An undefined
::: variable is treated as an empty string.
:::
::: M - Multi-line mode. The entire contents of stdin is read and
::: processed in one pass instead of line by line. ^ anchors
::: the beginning of a line and $ anchors the end of a line.
:::
::: X - Enables extended substitution pattern syntax with support
::: for the following escape sequences:
:::
::: \\ - Backslash
::: \b - Backspace
::: \f - Formfeed
::: \n - Newline
::: \r - Carriage Return
::: \t - Horizontal Tab
::: \v - Vertical Tab
::: \xnn - Ascii (Latin 1) character expressed as 2 hex digits
::: \unnnn - Unicode character expressed as 4 hex digits
:::
::: Escape sequences are supported even when the L option is used.
:::
::: S - The source is read from an environment variable instead of
::: from stdin. The name of the source environment variable is
::: specified in the next argument after the option string.
:::
::************ Batch portion ***********
#echo off
if .%2 equ . (
if "%~1" equ "/?" (
findstr "^:::" "%~f0" | cscript //E:JScript //nologo "%~f0" "^:::" ""
exit /b 0
) else (
call :err "Insufficient arguments"
exit /b 1
)
)
echo(%~3|findstr /i "[^SMILEX]" >nul && (
call :err "Invalid option(s)"
exit /b 1
)
cscript //E:JScript //nologo "%~f0" %*
exit /b 0
:err
>&2 echo ERROR: %~1. Use REPL /? to get help.
exit /b
************* JScript portion **********/
var env=WScript.CreateObject("WScript.Shell").Environment("Process");
var args=WScript.Arguments;
var search=args.Item(0);
var replace=args.Item(1);
var options="g";
if (args.length>2) {
options+=args.Item(2).toLowerCase();
}
var multi=(options.indexOf("m")>=0);
var srcVar=(options.indexOf("s")>=0);
if (srcVar) {
options=options.replace(/s/g,"");
}
if (options.indexOf("e")>=0) {
options=options.replace(/e/g,"");
search=env(search);
replace=env(replace);
}
if (options.indexOf("l")>=0) {
options=options.replace(/l/g,"");
search=search.replace(/([.^$*+?()[{\\|])/g,"\\$1");
replace=replace.replace(/\$/g,"$$$$");
}
if (options.indexOf("x")>=0) {
options=options.replace(/x/g,"");
replace=replace.replace(/\\\\/g,"\\B");
replace=replace.replace(/\\b/g,"\b");
replace=replace.replace(/\\f/g,"\f");
replace=replace.replace(/\\n/g,"\n");
replace=replace.replace(/\\r/g,"\r");
replace=replace.replace(/\\t/g,"\t");
replace=replace.replace(/\\v/g,"\v");
replace=replace.replace(/\\x[0-9a-fA-F]{2}|\\u[0-9a-fA-F]{4}/g,
function($0,$1,$2){
return String.fromCharCode(parseInt("0x"+$0.substring(2)));
}
);
replace=replace.replace(/\\B/g,"\\");
}
var search=new RegExp(search,options);
if (srcVar) {
WScript.Stdout.Write(env(args.Item(3)).replace(search,replace));
} else {
while (!WScript.StdIn.AtEndOfStream) {
if (multi) {
WScript.Stdout.Write(WScript.StdIn.ReadAll().replace(search,replace));
} else {
WScript.Stdout.WriteLine(WScript.StdIn.ReadLine().replace(search,replace));
}
}
}
:: Does %variable% =~ s/old/new/
setlocal ENABLEDELAYEDEXPANSION
for /f "delims=" %%a in ('echo !variable! ^|perl -pe "s/regexp/replace/" ') do set variable=%%a
The easiest and most flexible way to accomplish what you want would be to use awk (regexp examples) or sed (for example: sed -i -r -e "s/(\d+:\d\d\s+)\d+/\1replacementstring/g" filename) from GnuWin32, which both support Perl regexp syntax. I think what you're involved in is exactly what awk was designed for.
If you're stuck using only what's available without having to use 3rd party tools, you can perform regexp matches using vbscript. You can call vbscript by echoing the script to a .vbs file, calling cscript vbsfile, and capturing its output. Here's a proof of concept.
#echo off & setlocal enabledelayedexpansion
:: rxp.bat
:: rxp /? for usage instructions
if #%4==# goto usage
set global=false
set replace=false
for %%I in (%*) do (
if not #!next!==# (
if !next!==string set string=%%I
if !next!==pattern set pattern=%%I
if !next!==replace set replace=%%I
set next=
)
if #%%I==#/s set next=string
if #%%I==#/p set next=pattern
if #%%I==#/r set next=replace
if #%%I==#/g set global=true
)
if #%string==# goto usage
if #%pattern==# goto usage
set string=!string:"=""!
set string=!string:\=!
set pattern=!pattern:"=""!
set pattern=!pattern:\=!
if #!replace!==#false (
call :rxp !string:~1,-1! !pattern:~1,-1! !global!
) else (
set replace=!replace:"=""!
set replace=!replace:\=!
call :rxp !string:~1,-1! !pattern:~1,-1! !global! !replace:~1,-1!
)
goto :EOF
:rxp string pattern global replacement
echo Set rxp = New RegExp>regexp.vbs
echo rxp.Pattern = %2>>regexp.vbs
echo rxp.Global = %3>>regexp.vbs
if #%4==# (
echo Set res = rxp.Execute^(%1^)>>regexp.vbs
echo For Each match in res>>regexp.vbs
echo Wscript.Echo match.value>>regexp.vbs
echo Next>>regexp.vbs
) else (
echo Wscript.echo rxp.Replace^(%1, %4^)>>regexp.vbs
)
cscript /nologo regexp.vbs
del /q regexp.vbs
goto :EOF
:usage
echo Usage: %~nx0 /s "string" /p "regexp" [/g] [/r "replacement text"]
echo;
echo /s -- search string
echo;
echo /p -- regular expression pattern
echo Example: /p "<[^>]+>" to search for markup tags
echo matches ^<span class='a'^> or similar
echo;
echo /r -- replacement text (optional)
echo If specified, replace the matched text
echo Example: /p "(<div class=')blue('>)" /r "$1red$2"
echo matches ^<div class='blue'^>
echo replaces match with ^<div class='red'^>
echo;
echo /g -- global match (optional)
echo match every occurrence (matches only the first by default)
echo;
echo notes: If the regexp pattern includes capturing parentheses, use ^$1-^$9 as
echo backreferences in your replacement text. If any of your strings include
echo quotation marks, they can be escaped with a backslash (\).
echo;
echo Example:
echo %~nx0 /s "text begin <div id=\"foo\"> text end" /p "(<div)[^>]+(>)"
echo /r "$1 class=\"bar\"$2"
echo;
echo matches ^<div id="foo"^>, replaces match with ^<div class="bar"^>
echo output: text begin ^<div class="bar"^> text end
example output:
C:\Users\me\Desktop>rxp /s "7859 10000:00 7849 10000:00 (xfer#1, to-check=1033/1035)" /p "(\d+:\d\d\s+)\d+" /r "$1foo"
7859 10000:00 foo 10000:00 (xfer#1, to-check=1033/1035)
C:\Users\me\Desktop>rxp
Usage: rxp.bat /s "string" /p "regexp" [/g] [/r "replacement text"]
/s -- search string
/p -- regular expression pattern
Example: /p "<[^>]+>" to search for markup tags
matches <span class='a'> or similar
/r -- replacement text (optional)
If specified, replace the matched text
/g -- global match (optional)
match every occurrence (matches only the first by default)
notes: If the regexp pattern includes capturing parentheses, use $1-$9 as
backreferences in your replacement text. If any of your strings include
quotation marks, they can be escaped with a backslash (\).
Example:
rxp.bat /s "text begin <div id=\"foo\"> text end" /p "(<div)[^>]+(>)"
/r "$1 class=\"bar\"$2"
matches <div id="foo">, replaces match with <div class="bar">
output: text begin <div class="bar"> text end
Related
(EDITED) How can I read data from a text file and assign certain parts of it to variables? In the lines below, for example, I want to assign the data to variables where indicated but ignore the header line, the preface word "DATA:" and any quotation marks.
HEADER (ignore)
DATA: "set text inside quotes to VAR1"
DATA: "set text inside quotes to VAR2"
DATA (etc.)
The code I'm using is:
setlocal enabledelayedexpansion
set COUNT=0
for /f "usebackq delims=" %%a in ("data.txt") do (
set "INPUT=%%a"
set /a COUNT=!COUNT!+1
echo !INPUT! | findstr /i /c:"HEADER" > nul
if errorlevel 1 (
set "INPUT=!INPUT:DATA:=!"
set "INPUT=!INPUT:"=!"
set VAR!COUNT!=!INPUT!
echo Variable !COUNT! = !VAR!!COUNT!
)
)
My expected output is
Variable 1 = set text inside quotes to VAR1
Variable 2 = set text inside quotes to VAR2
but what I get is
Variable 2 = 2
Variable 3 = 3
Variable 4 = 4
What am I doing wrong?
I took your code and fixed it up.
In particular:
I switched the findstr to find all lines that do not match HEADER
I used arrays to store the variables.
It may need some minor tweaks to get it exactly as you want it, but I think I've given you a working outline.
#echo off
setlocal enabledelayedexpansion
set COUNT=0
for /f "tokens=*" %%a in ('findstr /i /v HEADER data.txt') do (
set "INPUT=%%a"
set /A COUNT=!COUNT!+1
set "INPUT=!INPUT:DATA:=!"
set VAR[!COUNT!]=!INPUT!
call echo Variable !COUNT! = %%VAR[!COUNT!]%%
)
Output:
Variable 1 = "set text inside quotes to VAR1"
Variable 2 = "set text inside quotes to VAR2"
Variable 3 = DATA (etc.)
To match lines that have leading spaces, use switches:
findstr /V /R /C:"^ *HEADER"
The regular expression means:
^ : Beginning of line
[space] : a literal space
* : the previous character (space) repeated as many times as needed
HEADER : the text to find after leading spaces
The switches mean:
/R Use Regular Expressions
/C: Use this search-string
/V Show all lines that do NOT match this expression.
I have written a windows batch code to rename the folders and files recursively from V34 to 35 and so on..and but I need to change same V34 to 35 inside a text file,which is residing inside the files
Folder---file--text file(Inside the text file need to change the V34 content to V35)
Please find the below code which I have written and let me know for the changes
#echo off
setlocal disableDelayedExpansion
set "old=V34"
set "new=V35"
for /f "delims=" %%F in ('dir /b /s *. *.xslt ^| sort /r') do (
set "source=%%F"
set "oldname=%%~nxF"
setlocal enableDelayedExpansion
set "newname=!oldname:%old%=%new%!"
if /i "!newname!" neq "!oldname!" (
echo ren "!source!" "!newname!"
ren "!source!" "!newname!"
) )
for /f "delims=" %%i in (.*) do (
set "source=%%i"
setlocal enabledelayedexpansion
set "newname=!oldname:%old%=%new%!"
echo ren "!source!" "!newname!"
ren "!source!" "!newname!"
endlocal
)
endlocal
simple solution use powershell for get all folder and file names then rename to new name see this example
get-childitem -filter *v34.txt | foreach { (Get-Content drive:\$_ ) | ForEach-Object { $_ -replace "v34", "v35" } | Set-Content v35.txt
for cmd you can get-content and then replace v34 to v35
type v34.txt|repl "v34" "v35" >v35.txt
for change content of txt file you can use fnrtooland down is example for you but still i suggest to you use powershell
for your code
.\fnr.exe --cl --dir "c:\" --filemask "*.txt" --find "v34" --replace "v35" --includeSubDirectories
your code :
#echo off
setlocal disableDelayedExpansion
set "old=V34"
set "new=V35"
for /f "delims=" %%F in ('dir /b /s *. *.xslt ^| sort /r') do (
set "source=%%F"
set "oldname=%%~nxF"
setlocal enableDelayedExpansion
set "newname=!oldname:%old%=%new%!"
if /i "!newname!" neq "!oldname!" (
echo ren "!source!" "!newname!"
ren "!source!" "!newname!"
) )
for /f "delims=" %%i in (.*) do (
set "source=%%i"
setlocal enabledelayedexpansion
set "newname=!oldname:%old%=%new%!"
echo ren "!source!" "!newname!"
ren "!source!" "!newname!"
endlocal
)
endlocal
complete code :
#echo off
setlocal disableDelayedExpansion
set "old=V34"
set "new=V35"
for /f "delims=" %%F in ('dir /b /s *. *.xslt ^| sort /r') do (
set "source=%%F"
set "oldname=%%~nxF"
setlocal enableDelayedExpansion
set "newname=!oldname:%old%=%new%!"
if /i "!newname!" neq "!oldname!" (
echo ren "!source!" "!newname!"
ren "!source!" "!newname!"
) )
c:\path\fnr.exe --cl --dir "c:\" --filemask "*.txt" --find "v34" --replace "v35" --includeSubDirectories
endlocal
batfile for replace with regex :
#if (#X)==(#Y) #end /* find string and replace
::************ Documentation ***********
::REPL.BAT version 6.2
:::
:::REPL Search Replace [Options [SourceVar]]
:::REPL /?[REGEX|REPLACE]
:::REPL /V
:::
::: Performs a global regular expression search and replace operation on
::: each line of input from stdin and prints the result to stdout.
:::
::: Each parameter may be optionally enclosed by double quotes. The double
::: quotes are not considered part of the argument. The quotes are required
::: if the parameter contains a batch token delimiter like space, tab, comma,
::: semicolon. The quotes should also be used if the argument contains a
::: batch special character like &, |, etc. so that the special character
::: does not need to be escaped with ^.
:::
::: If called with a single argument of /?, then prints help documentation
::: to stdout. If a single argument of /?REGEX, then opens up Microsoft's
::: JScript regular expression documentation within your browser. If a single
::: argument of /?REPLACE, then opens up Microsoft's JScript REPLACE
::: documentation within your browser.
:::
::: If called with a single argument of /V, case insensitive, then prints
::: the version of REPL.BAT.
:::
::: Search - By default, this is a case sensitive JScript (ECMA) regular
::: expression expressed as a string.
:::
::: JScript regex syntax documentation is available at
::: http://msdn.microsoft.com/en-us/library/ae5bf541(v=vs.80).aspx
:::
::: Replace - By default, this is the string to be used as a replacement for
::: each found search expression. Full support is provided for
::: substituion patterns available to the JScript replace method.
:::
::: For example, $& represents the portion of the source that matched
::: the entire search pattern, $1 represents the first captured
::: submatch, $2 the second captured submatch, etc. A $ literal
::: can be escaped as $$.
:::
::: An empty replacement string must be represented as "".
:::
::: Replace substitution pattern syntax is fully documented at
::: http://msdn.microsoft.com/en-US/library/efy6s3e6(v=vs.80).aspx
:::
::: Options - An optional string of characters used to alter the behavior
::: of REPL. The option characters are case insensitive, and may
::: appear in any order.
:::
::: A - Only print altered lines. Unaltered lines are discarded.
::: If the S options is present, then prints the result only if
::: there was a change anywhere in the string. The A option is
::: incompatible with the M option unless the S option is present.
:::
::: B - The Search must match the beginning of a line.
::: Mostly used with literal searches.
:::
::: E - The Search must match the end of a line.
::: Mostly used with literal searches.
:::
::: I - Makes the search case-insensitive.
:::
::: J - The Replace argument represents a JScript expression.
::: The expression may access an array like arguments object
::: named $. However, $ is not a true array object.
:::
::: The $.length property contains the total number of arguments
::: available. The $.length value is equal to n+3, where n is the
::: number of capturing left parentheses within the Search string.
:::
::: $[0] is the substring that matched the Search,
::: $[1] through $[n] are the captured submatch strings,
::: $[n+1] is the offset where the match occurred, and
::: $[n+2] is the original source string.
:::
::: Arguments $[0] through $[10] may be abbreviated as
::: $1 through $10. Argument $[11] and above must use the square
::: bracket notation.
:::
::: L - The Search is treated as a string literal instead of a
::: regular expression. Also, all $ found in the Replace string
::: are treated as $ literals.
:::
::: M - Multi-line mode. The entire contents of stdin is read and
::: processed in one pass instead of line by line, thus enabling
::: search for \n. This also enables preservation of the original
::: line terminators. If the M option is not present, then every
::: printed line is terminated with carriage return and line feed.
::: The M option is incompatible with the A option unless the S
::: option is also present.
:::
::: Note: If working with binary data containing NULL bytes,
::: then the M option must be used.
:::
::: S - The source is read from an environment variable instead of
::: from stdin. The name of the source environment variable is
::: specified in the next argument after the option string. Without
::: the M option, ^ anchors the beginning of the string, and $ the
::: end of the string. With the M option, ^ anchors the beginning
::: of a line, and $ the end of a line.
:::
::: V - Search and Replace represent the name of environment
::: variables that contain the respective values. An undefined
::: variable is treated as an empty string.
:::
::: X - Enables extended substitution pattern syntax with support
::: for the following escape sequences within the Replace string:
:::
::: \\ - Backslash
::: \b - Backspace
::: \f - Formfeed
::: \n - Newline
::: \q - Quote
::: \r - Carriage Return
::: \t - Horizontal Tab
::: \v - Vertical Tab
::: \xnn - Extended ASCII byte code expressed as 2 hex digits
::: \unnnn - Unicode character expressed as 4 hex digits
:::
::: Also enables the \q escape sequence for the Search string.
::: The other escape sequences are already standard for a regular
::: expression Search string.
:::
::: Also modifies the behavior of \xnn in the Search string to work
::: properly with extended ASCII byte codes.
:::
::: Extended escape sequences are supported even when the L option
::: is used. Both Search and Replace support all of the extended
::: escape sequences if both the X and L opions are combined.
:::
::: Return Codes: 0 = At least one change was made
::: or the /? or /V option was used
:::
::: 1 = No change was made
:::
::: 2 = Invalid call syntax or incompatible options
:::
::: 3 = JScript runtime error, typically due to invalid regex
:::
::: REPL.BAT was written by Dave Benham, with assistance from DosTips user Aacini
::: to get \xnn to work properly with extended ASCII byte codes. Also assistance
::: from DosTips user penpen diagnosing issues reading NULL bytes, along with a
::: workaround. REPL.BAT was originally posted at:
::: http://www.dostips.com/forum/viewtopic.php?f=3&t=3855
:::
::************ Batch portion ***********
#echo off
if .%2 equ . (
if "%~1" equ "/?" (
<"%~f0" cscript //E:JScript //nologo "%~f0" "^:::" "" a
exit /b 0
) else if /i "%~1" equ "/?regex" (
explorer "http://msdn.microsoft.com/en-us/library/ae5bf541(v=vs.80).aspx"
exit /b 0
) else if /i "%~1" equ "/?replace" (
explorer "http://msdn.microsoft.com/en-US/library/efy6s3e6(v=vs.80).aspx"
exit /b 0
) else if /i "%~1" equ "/V" (
<"%~f0" cscript //E:JScript //nologo "%~f0" "^::(REPL\.BAT version)" "$1" a
exit /b 0
) else (
call :err "Insufficient arguments"
exit /b 2
)
)
echo(%~3|findstr /i "[^SMILEBVXAJ]" >nul && (
call :err "Invalid option(s)"
exit /b 2
)
echo(%~3|findstr /i "M"|findstr /i "A"|findstr /vi "S" >nul && (
call :err "Incompatible options"
exit /b 2
)
cscript //E:JScript //nologo "%~f0" %*
exit /b %errorlevel%
:err
>&2 echo ERROR: %~1. Use REPL /? to get help.
exit /b
************* JScript portion **********/
var rtn=1;
try {
var env=WScript.CreateObject("WScript.Shell").Environment("Process");
var args=WScript.Arguments;
var search=args.Item(0);
var replace=args.Item(1);
var options="g";
if (args.length>2) options+=args.Item(2).toLowerCase();
var multi=(options.indexOf("m")>=0);
var alterations=(options.indexOf("a")>=0);
if (alterations) options=options.replace(/a/g,"");
var srcVar=(options.indexOf("s")>=0);
if (srcVar) options=options.replace(/s/g,"");
var jexpr=(options.indexOf("j")>=0);
if (jexpr) options=options.replace(/j/g,"");
if (options.indexOf("v")>=0) {
options=options.replace(/v/g,"");
search=env(search);
replace=env(replace);
}
if (options.indexOf("x")>=0) {
options=options.replace(/x/g,"");
if (!jexpr) {
replace=replace.replace(/\\\\/g,"\\B");
replace=replace.replace(/\\q/g,"\"");
replace=replace.replace(/\\x80/g,"\\u20AC");
replace=replace.replace(/\\x82/g,"\\u201A");
replace=replace.replace(/\\x83/g,"\\u0192");
replace=replace.replace(/\\x84/g,"\\u201E");
replace=replace.replace(/\\x85/g,"\\u2026");
replace=replace.replace(/\\x86/g,"\\u2020");
replace=replace.replace(/\\x87/g,"\\u2021");
replace=replace.replace(/\\x88/g,"\\u02C6");
replace=replace.replace(/\\x89/g,"\\u2030");
replace=replace.replace(/\\x8[aA]/g,"\\u0160");
replace=replace.replace(/\\x8[bB]/g,"\\u2039");
replace=replace.replace(/\\x8[cC]/g,"\\u0152");
replace=replace.replace(/\\x8[eE]/g,"\\u017D");
replace=replace.replace(/\\x91/g,"\\u2018");
replace=replace.replace(/\\x92/g,"\\u2019");
replace=replace.replace(/\\x93/g,"\\u201C");
replace=replace.replace(/\\x94/g,"\\u201D");
replace=replace.replace(/\\x95/g,"\\u2022");
replace=replace.replace(/\\x96/g,"\\u2013");
replace=replace.replace(/\\x97/g,"\\u2014");
replace=replace.replace(/\\x98/g,"\\u02DC");
replace=replace.replace(/\\x99/g,"\\u2122");
replace=replace.replace(/\\x9[aA]/g,"\\u0161");
replace=replace.replace(/\\x9[bB]/g,"\\u203A");
replace=replace.replace(/\\x9[cC]/g,"\\u0153");
replace=replace.replace(/\\x9[dD]/g,"\\u009D");
replace=replace.replace(/\\x9[eE]/g,"\\u017E");
replace=replace.replace(/\\x9[fF]/g,"\\u0178");
replace=replace.replace(/\\b/g,"\b");
replace=replace.replace(/\\f/g,"\f");
replace=replace.replace(/\\n/g,"\n");
replace=replace.replace(/\\r/g,"\r");
replace=replace.replace(/\\t/g,"\t");
replace=replace.replace(/\\v/g,"\v");
replace=replace.replace(/\\x[0-9a-fA-F]{2}|\\u[0-9a-fA-F]{4}/g,
function($0,$1,$2){
return String.fromCharCode(parseInt("0x"+$0.substring(2)));
}
);
replace=replace.replace(/\\B/g,"\\");
}
search=search.replace(/\\\\/g,"\\B");
search=search.replace(/\\q/g,"\"");
search=search.replace(/\\x80/g,"\\u20AC");
search=search.replace(/\\x82/g,"\\u201A");
search=search.replace(/\\x83/g,"\\u0192");
search=search.replace(/\\x84/g,"\\u201E");
search=search.replace(/\\x85/g,"\\u2026");
search=search.replace(/\\x86/g,"\\u2020");
search=search.replace(/\\x87/g,"\\u2021");
search=search.replace(/\\x88/g,"\\u02C6");
search=search.replace(/\\x89/g,"\\u2030");
search=search.replace(/\\x8[aA]/g,"\\u0160");
search=search.replace(/\\x8[bB]/g,"\\u2039");
search=search.replace(/\\x8[cC]/g,"\\u0152");
search=search.replace(/\\x8[eE]/g,"\\u017D");
search=search.replace(/\\x91/g,"\\u2018");
search=search.replace(/\\x92/g,"\\u2019");
search=search.replace(/\\x93/g,"\\u201C");
search=search.replace(/\\x94/g,"\\u201D");
search=search.replace(/\\x95/g,"\\u2022");
search=search.replace(/\\x96/g,"\\u2013");
search=search.replace(/\\x97/g,"\\u2014");
search=search.replace(/\\x98/g,"\\u02DC");
search=search.replace(/\\x99/g,"\\u2122");
search=search.replace(/\\x9[aA]/g,"\\u0161");
search=search.replace(/\\x9[bB]/g,"\\u203A");
search=search.replace(/\\x9[cC]/g,"\\u0153");
search=search.replace(/\\x9[dD]/g,"\\u009D");
search=search.replace(/\\x9[eE]/g,"\\u017E");
search=search.replace(/\\x9[fF]/g,"\\u0178");
if (options.indexOf("l")>=0) {
search=search.replace(/\\b/g,"\b");
search=search.replace(/\\f/g,"\f");
search=search.replace(/\\n/g,"\n");
search=search.replace(/\\r/g,"\r");
search=search.replace(/\\t/g,"\t");
search=search.replace(/\\v/g,"\v");
search=search.replace(/\\x[0-9a-fA-F]{2}|\\u[0-9a-fA-F]{4}/g,
function($0,$1,$2){
return String.fromCharCode(parseInt("0x"+$0.substring(2)));
}
);
search=search.replace(/\\B/g,"\\");
} else search=search.replace(/\\B/g,"\\\\");
}
if (options.indexOf("l")>=0) {
options=options.replace(/l/g,"");
search=search.replace(/([.^$*+?()[{\\|])/g,"\\$1");
if (!jexpr) replace=replace.replace(/\$/g,"$$$$");
}
if (options.indexOf("b")>=0) {
options=options.replace(/b/g,"");
search="^"+search
}
if (options.indexOf("e")>=0) {
options=options.replace(/e/g,"");
search=search+"$"
}
var search=new RegExp(search,options);
var str1, str2;
if (srcVar) {
str1=env(args.Item(3));
str2=str1.replace(search,jexpr?replFunc:replace);
if (!alterations || str1!=str2) if (multi) {
WScript.Stdout.Write(str2);
} else {
WScript.Stdout.WriteLine(str2);
}
if (str1!=str2) rtn=0;
} else if (multi){
var buf=1024;
str1="";
while (!WScript.StdIn.AtEndOfStream) {
str1+=WScript.StdIn.Read(buf);
buf*=2
}
str2=str1.replace(search,jexpr?replFunc:replace);
WScript.Stdout.Write(str2);
if (str1!=str2) rtn=0;
} else {
while (!WScript.StdIn.AtEndOfStream) {
str1=WScript.StdIn.ReadLine();
str2=str1.replace(search,jexpr?replFunc:replace);
if (!alterations || str1!=str2) WScript.Stdout.WriteLine(str2);
if (str1!=str2) rtn=0;
}
}
} catch(e) {
WScript.Stderr.WriteLine("JScript runtime error: "+e.message);
rtn=3;
}
WScript.Quit(rtn);
function replFunc($0, $1, $2, $3, $4, $5, $6, $7, $8, $9, $10) {
var $=arguments;
return(eval(replace));
}
example :
for /f %g in ( 'dir /a/b /s s:\' ) do type %g | findstr "v34" | repel.bat "v34" "v35"
resource for repel.bat link
I have a comma-delimited text file with three fields. The first always containd a string, but the second, third, or both can be empty. When all contain strings, when only the third is emppty, and when the second and third are both empty, I get the expected result when it is read using the FOR command, the expected result being that the variables read from fields containing strings are equal to those strings, and the variables read from empty fields have null values. However, when the second fielkd is empty, and the third field contains a string, I get the unexpected result that the second variable, the one that was supposed to be read from the second field equals the contents of the third field, and the third variable has a null value.
How can I work around this problem?
This information is copied verbatim from my DosTips post: Safely parse nearly any CSV with parseCSV.bat
It is fairly common that someone wants to parse CSV using FOR /F. This is a simple task if you know all columns are populated, and there are no commas, newlines, or quotes within values. Assume there are 4 columns:
#echo off
for /f "tokens=1-4 delims=," %%A in (test.csv) do (
echo ----------------------
echo A=%%~A
echo B=%%~B
echo C=%%~C
echo D=%%~D
echo(
)
But things become more difficult if any of the following conditions occur:
1) Values may be empty, with consecutive commas. FOR /F treats consecutive delimiters as one, so it will throw off the column assignment.
2) Quoted values may contain commas. FOR /F will incorrectly treat a quoted comma as a column delimiter.
3) Quoted values may contain newlines. FOR /F will break the line at the newline and incorrectly treat the one row as two.
4) Quoted values may contain paired quotes that represent one quote. For example, "He said, ""Hello there"". A method is needed to convert "" into ".
Then there is a secondary problems that can crop up if delayed expansion is enabled.
5) A FOR variable %%A will be corrupted if it contains ! (or sometimes ^) if delayed expansion is enabled when the variable is expanded.
There are fairly easy solutions for some of these issues, but solving all of them is extremely difficult (and slow) with pure batch.
I have written a hybrid JScript/batch utility called parseCSV.bat that makes it easy and relatively efficient to correctly parse nearly any CSV file with FOR /F.
parseCSV.bat
#if (#X)==(#Y) #end /* harmless hybrid line that begins a JScrpt comment
::************ Documentation ***********
::parseCSV.bat version 1.0
:::
:::parseCSV [/option]...
:::
::: Parse stdin as CSV and write it to stdout in a way that can be safely
::: parsed by FOR /F. All columns will be enclosed by quotes so that empty
::: columns may be preserved. It also supports delimiters, newlines, and
::: quotes within quoted values. Two consecutive quotes within a quoted value
::: are converted into one quote.
:::
::: Available options:
:::
::: /I:string = Input delimiter. Default is a comma.
:::
::: /O:string = Output delimiter. Default is a comma.
:::
::: /E = Encode output delimiter in value as \D
::: Encode newline in value as \N
::: Encode backslash in value as \S
:::
::: /D = Escape exclamation point and caret for delayed expansion
::: ! becomes ^!
::: ^ becomes ^^
:::
:::parseCSV /?
:::
::: Display this help
:::
:::parseCSV /V
:::
::: Display the version of parseCSV.bat
:::
:::parseCSV.bat was written by Dave Benham. Updates are available at the original
:::posting site: http://www.dostips.com/forum/viewtopic.php?f=3&t=5702
:::
::************ Batch portion ***********
#echo off
if "%~1" equ "/?" (
setlocal disableDelayedExpansion
for /f "delims=: tokens=*" %%A in ('findstr "^:::" "%~f0"') do echo(%%A
exit /b 0
)
if /i "%~1" equ "/V" (
for /f "delims=:" %%A in ('findstr /bc:"::%~nx0 version " "%~f0"') do echo %%A
exit /b 0
)
cscript //E:JScript //nologo "%~f0" %*
exit /b 0
************ JScript portion ***********/
var args = WScript.Arguments.Named,
stdin = WScript.Stdin,
stdout = WScript.Stdout,
escape = args.Exists("E"),
delayed = args.Exists("D"),
inDelim = args.Exists("I") ? args.Item("I") : ",",
outDelim = args.Exists("O") ? args.Item("O") : ",",
quote = false,
ln, c, n;
while (!stdin.AtEndOfStream) {
ln=stdin.ReadLine();
if (!quote) stdout.Write('"');
for (n=0; n<ln.length; n++ ) {
c=ln.charAt(n);
if (c == '"') {
if (quote && ln.charAt(n+1) == '"') {
n++;
} else {
quote=!quote;
continue;
}
}
if (c == inDelim && !quote) c='"'+outDelim+'"';
if (escape) {
if (c == outDelim) c="\\D";
if (c == "\\") c="\\S";
}
if (delayed) {
if (c == "!") c="^!";
if (c == "^") c="^^";
}
stdout.Write(c);
}
stdout.Write( (quote) ? ((escape) ? "\\N" : "\n") : '"\n' );
}
I have also written a script that defines a macro to assist with parsing the most problematic CSV files. See http://www.dostips.com/forum/viewtopic.php?f=3&t=1827 for background information about batch macros with arguments.
define_csvGetCol.bat
::define_csvGetCol.bat version 1.1
::
:: Defines variable LF and macro csvGetCol to be used with
:: parseCSV.bat to parse nearly any CSV file.
::
:: This script must be called with delayedExpansion disabled.
::
:: The %csvGetCol% macro must be used with delayedExpansion enabled.
::
:: Example usage:
::
:: #echo off
:: setlocal disableDelayedExpansion
:: call define_csvGetCol
:: setlocal enableDelayedExpansion
:: for /f "tokens=1-3 delims=," %%A in ('parseCSV /d /e ^<test.csv') do (
:: %== Load and decode column values ==%
:: %csvGetCol% A "," %%A
:: %csvGetCol% B "," %%B
:: %csvGetCol% C "," %%C
:: %== Display the result ==%
:: echo ----------------------
:: for %%V in (A B C) do echo %%V=!%%V!
:: echo(
:: )
::
:: Written by Dave Benham
::
:: Delayed expansion must be disabled during macro definition
:: Define LF to contain a linefeed (0x0A) character
set ^"LF=^
^" The empty line above is critical - DO NOT REMOVE
:: define a newline with line continuation
set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"
:: Define csvGetCol
:: %csvGetCol% envVarName "Delimiter" FORvar
set csvGetCol=for %%# in (1 2) do if %%#==2 (%\n%
setlocal enableDelayedExpansion^&for /f "tokens=1,2*" %%1 in ("!args!") do (%\n%
endlocal^&endlocal%\n%
set "%%1=%%~3"!%\n%
if defined %%1 (%\n%
for %%L in ("!LF!") do set "%%1=!%%1:\N=%%~L!"%\n%
set "%%1=!%%1:\D=%%~2!"%\n%
set "%%1=!%%1:\S=\!"%\n%
)%\n%
)) else setlocal disableDelayedExpansion ^& set args=
Usage is extremely simple if you know there are no commas or newlines in any values, and delayed expansion is not needed:
test1.csv
"value1 with ""quotes""",value2: No problem!,value3: 2^3=8,value4: (2^2)!=16
value1,,value3,value4
value1,,,value4
value1,,,
,,,value4
test1.bat - no delayed expansion, no commas or newlines in values
#echo off
for /f "tokens=1-4 delims=," %%A in ('parseCSV ^<test1.csv') do (
echo -------------
echo(A=%%~A
echo(B=%%~B
echo(C=%%~C
echo(D=%%~D
echo(
)
--OUTPUT1--
-------------
A=value1 with "quotes"
B=value2: No problem!
C=value3: 2^3=8
D=value4: (2^2)!=16
-------------
A=value1
B=
C=value3
D=value4
-------------
A=value1
B=
C=
D=value4
-------------
A=value1
B=
C=
D=
-------------
A=
B=
C=
D=value4
It is also quite simple when commas are in values if you know of a character that does not exist in any value. Simply specify a unique character for the output delimiter.
test2.csv
"value1 with ""quotes""","value2, No problem!","value3, 2^3=8","value4, (2^2)!=16"
value1,,value3,value4
value1,,,value4
value1,,,
,,,value4
test2.bat - no delayed expansion, no newlines or pipes in values. Note that the entire option must be quoted if the delimiter is a poison character
#echo off
for /f "tokens=1-4 delims=|" %%A in ('parseCSV "/o:|" ^<test2.csv') do (
echo -------------
echo(A=%%~A
echo(B=%%~B
echo(C=%%~C
echo(D=%%~D
echo(
)
--OUTPUT2--
-------------
A=value1 with "quotes"
B=value2, No problem!
C=value3, 2^3=8
D=value4, (2^2)!=16
-------------
A=value1
B=
C=value3
D=value4
-------------
A=value1
B=
C=
D=value4
-------------
A=value1
B=
C=
D=
-------------
A=
B=
C=
D=value4
It only takes a bit more code if values may contain newlines or if you don't know of a character that does not appear in any value. This solution encodes newlines, delimiters, and slashes as \N, \D, and \S. Delayed expansion is needed within the loop to decode the values, so ! and ^ must be escaped as ^! and ^^.
test3.csv
"2^3=8","(2^2)!=16","Success!",Value4
value1,value2,value3,value4
,,,value4
"value1","value2","value3","value4"
"He said, ""Hey cutie.""","She said, ""Drop dead!""","value3 line1
value3 line2",c:\Windows
test3.bat - Allow virtually any valid CSV, without using a macro.
#echo off
setlocal enableDelayedExpansion
:: Define LF to contain a linefeed (0x0A) character
set ^"LF=^
^" The empty line above is critical - DO NOT REMOVE
for /f "tokens=1-4 delims=," %%A in ('parseCSV /e /d ^<test3.csv') do (
%== Load columns with encoded values. The trailing ! is important ==%
set "A=%%~A"!
set "B=%%~B"!
set "C=%%~C"!
set "D=%%~D"!
%== Decode values ==%
for %%L in ("!LF!") do for %%V in (A B C D) do if defined %%V (
set "%%V=!%%V:\N=%%~L!"
set "%%V=!%%V:\D=,!"
set "%%V=!%%V:\S=\!"
)
%== Print results ==%
echo ---------------------
for %%V in (A B C D) do echo(%%V=!%%V!
echo(
)
--OUTPUT3--
---------------------
A=2^3=8
B=(2^2)!=16
C=Success!
D=Value4
---------------------
A=value1
B=value2
C=value3
D=value4
---------------------
A=
B=
C=
D=value4
---------------------
A=value1
B=value2
C=value3
D=value4
---------------------
A=He said, "Hey cutie."
B=She said, "Drop dead!"
C=value3 line1
value3 line2
D=c:\Windows
test4.bat - Allow virtually any valid CSV, but now use the %csvGetCol% macro.
#echo off
:: Delayed expansion must be disabled during macro definition
setlocal disableDelayedExpansion
call define_csvGetCol
:: Delayed expansion must be enabled when using %csvGetCol%
setlocal enableDelayedExpansion
for /f "tokens=1-4 delims=," %%A in ('parseCSV /e /d ^<test3.csv') do (
%== Load and decode column values ==%
%csvGetCol% A "," %%A
%csvGetCol% B "," %%B
%csvGetCol% C "," %%C
%csvGetCol% D "," %%D
%== Print results ==%
echo ---------------------
for %%V in (A B C D) do echo(%%V=!%%V!
echo(
)
Output is identical to test3.bat
If the CSV file is very large, then it is much more efficient to save the output of parseCSV.bat to a temporary file, and then use the FOR /F loop to read the temporary file.
There are still a couple inherent limitations that are true for all FOR /F usage:
1) A single FOR /F cannot parse more than 32 columns.
2) Batch line length restriction of 8191 characters can still be a problem.
No sample data, so solution incomplete.
#ECHO OFF
SETLOCAL enabledelayedexpansion
(
FOR /f "delims=" %%a IN (q27830845.txt) DO (
SET "line=%%a"
SET "line=!line:,,,= , , ,!"
SET "line=!line:,,= , ,!"
FOR /f "tokens=1-4delims=," %%b IN ("!LINE!") DO (
ECHO(%%a--^>^>%%b++%%c++%%d++%%e++
)
)
)>newfile.txt
GOTO :EOF
I used a file named q27830845.txt containing this data for my testing.
col1,col 2,col 3,col4
one,two,three,four
ONE,,THREE,FOUR - no two
ONE,,,FOUR - 3 and 2 missing
,,,Only FOUR
Produces newfile.txt with content
col1,col 2,col 3,col4-->>col1++col 2++col 3++col4++
one,two,three,four-->>one++two++three++four++
ONE,,THREE,FOUR - no two-->>ONE ++ ++THREE++FOUR - no two++
ONE,,,FOUR - 3 and 2 missing-->>ONE ++ ++ ++FOUR - 3 and 2 missing++
,,,Only FOUR-->> ++ ++ ++Only FOUR++
Note that %%a etc may have Space appended. Will no doubt show sensitivity to the characters which have meaning to cmd like ! and %. ++ used simply as an obvious visual separator between fields.
I need a batch file contents to copy file A to file B after removing the CR LF
I have found the following but it is simply taking actual value of %1 and putting into a file without cr lf.
REM Copy and Remove Line Feeds
#echo off
echo %1> %2
rem <nul set /p ".=%1 > c:/temp/%2.txt
I need to remove all the CR LFs from File A and put the results in File B
The Batch file below do what you want in the fastest way:
#echo off
setlocal DisableDelayedExpansion
(for /F "usebackq delims=" %%a in (%1) do (
set /P "=%%a" < NUL
)) > %2
You must put files A and B in the parameters: test.bat A.txt B.txt
Antonio
There are a number of free 3rd party utilities that could be downloaded to make this task easy.
I have written a REPL.BAT hybrid batch/JScript utility that conveinently performs regex search and replace on files. It is extremely flexible and quite fast.
It is very easy to do what you want with this utility.
type A.txt|repl "\r|\n" "" m >B.txt
Here is the REPL.BAT script. Full documentation is embedded within the script:
#if (#X)==(#Y) #end /* Harmless hybrid line that begins a JScript comment
::************ Documentation ***********
:::
:::REPL Search Replace [Options [SourceVar]]
:::REPL /?
:::
::: Performs a global search and replace operation on each line of input from
::: stdin and prints the result to stdout.
:::
::: Each parameter may be optionally enclosed by double quotes. The double
::: quotes are not considered part of the argument. The quotes are required
::: if the parameter contains a batch token delimiter like space, tab, comma,
::: semicolon. The quotes should also be used if the argument contains a
::: batch special character like &, |, etc. so that the special character
::: does not need to be escaped with ^.
:::
::: If called with a single argument of /? then prints help documentation
::: to stdout.
:::
::: Search - By default this is a case sensitive JScript (ECMA) regular
::: expression expressed as a string.
:::
::: JScript syntax documentation is available at
::: http://msdn.microsoft.com/en-us/library/ae5bf541(v=vs.80).aspx
:::
::: Replace - By default this is the string to be used as a replacement for
::: each found search expression. Full support is provided for
::: substituion patterns available to the JScript replace method.
::: A $ literal can be escaped as $$. An empty replacement string
::: must be represented as "".
:::
::: Replace substitution pattern syntax is documented at
::: http://msdn.microsoft.com/en-US/library/efy6s3e6(v=vs.80).aspx
:::
::: Options - An optional string of characters used to alter the behavior
::: of REPL. The option characters are case insensitive, and may
::: appear in any order.
:::
::: I - Makes the search case-insensitive.
:::
::: L - The Search is treated as a string literal instead of a
::: regular expression. Also, all $ found in Replace are
::: treated as $ literals.
:::
::: E - Search and Replace represent the name of environment
::: variables that contain the respective values. An undefined
::: variable is treated as an empty string.
:::
::: M - Multi-line mode. The entire contents of stdin is read and
::: processed in one pass instead of line by line. ^ anchors
::: the beginning of a line and $ anchors the end of a line.
:::
::: X - Enables extended substitution pattern syntax with support
::: for the following escape sequences:
:::
::: \\ - Backslash
::: \b - Backspace
::: \f - Formfeed
::: \n - Newline
::: \r - Carriage Return
::: \t - Horizontal Tab
::: \v - Vertical Tab
::: \xnn - Ascii (Latin 1) character expressed as 2 hex digits
::: \unnnn - Unicode character expressed as 4 hex digits
:::
::: Escape sequences are supported even when the L option is used.
:::
::: S - The source is read from an environment variable instead of
::: from stdin. The name of the source environment variable is
::: specified in the next argument after the option string.
:::
::************ Batch portion ***********
#echo off
if .%2 equ . (
if "%~1" equ "/?" (
findstr "^:::" "%~f0" | cscript //E:JScript //nologo "%~f0" "^:::" ""
exit /b 0
) else (
call :err "Insufficient arguments"
exit /b 1
)
)
echo(%~3|findstr /i "[^SMILEX]" >nul && (
call :err "Invalid option(s)"
exit /b 1
)
cscript //E:JScript //nologo "%~f0" %*
exit /b 0
:err
>&2 echo ERROR: %~1. Use REPL /? to get help.
exit /b
************* JScript portion **********/
var env=WScript.CreateObject("WScript.Shell").Environment("Process");
var args=WScript.Arguments;
var search=args.Item(0);
var replace=args.Item(1);
var options="g";
if (args.length>2) {
options+=args.Item(2).toLowerCase();
}
var multi=(options.indexOf("m")>=0);
var srcVar=(options.indexOf("s")>=0);
if (srcVar) {
options=options.replace(/s/g,"");
}
if (options.indexOf("e")>=0) {
options=options.replace(/e/g,"");
search=env(search);
replace=env(replace);
}
if (options.indexOf("l")>=0) {
options=options.replace(/l/g,"");
search=search.replace(/([.^$*+?()[{\\|])/g,"\\$1");
replace=replace.replace(/\$/g,"$$$$");
}
if (options.indexOf("x")>=0) {
options=options.replace(/x/g,"");
replace=replace.replace(/\\\\/g,"\\B");
replace=replace.replace(/\\b/g,"\b");
replace=replace.replace(/\\f/g,"\f");
replace=replace.replace(/\\n/g,"\n");
replace=replace.replace(/\\r/g,"\r");
replace=replace.replace(/\\t/g,"\t");
replace=replace.replace(/\\v/g,"\v");
replace=replace.replace(/\\x[0-9a-fA-F]{2}|\\u[0-9a-fA-F]{4}/g,
function($0,$1,$2){
return String.fromCharCode(parseInt("0x"+$0.substring(2)));
}
);
replace=replace.replace(/\\B/g,"\\");
}
var search=new RegExp(search,options);
if (srcVar) {
WScript.Stdout.Write(env(args.Item(3)).replace(search,replace));
} else {
while (!WScript.StdIn.AtEndOfStream) {
if (multi) {
WScript.Stdout.Write(WScript.StdIn.ReadAll().replace(search,replace));
} else {
WScript.Stdout.WriteLine(WScript.StdIn.ReadLine().replace(search,replace));
}
}
}
I'm attempting to rewrite a configuration file using a Windows Batch file.
I'm looping through the lines of the file and looking for the line that I want to replace with a specified new line.
I have a 'function' that writes the line to the file
:AddText %1 %2
set Text=%~1%
set NewLine=%~2%
echo "%Text%" | findstr /C:"%markerstr%" 1>nul
if errorlevel 1 (
if not "%Text%" == "" (
setlocal EnableDelayedExpansion
(
echo !Text!
) >> outfile.txt
) else (
echo. >> outfile.txt
)
) else (
set NewLine=%NewLine"=%
setlocal EnableDelayedExpansion
(
echo !NewLine!
) >> outfile.txt
)
exit /b
The problem is when %Text% is a string with embedded double quotes.
Then it fails. Possibly there are other characters that would cause it to fail too.
How can I get this to be able to work with all text found in the configuration file?
Try replacing all " in Text with ^".
^ is escape character so the the " will be treated as regular character
you can try the following:
:AddText %1 %2
set _Text=%~1%
set Text=%_Text:"=^^^"%
... rest of your code
REM for example if %1 is "blah"blah"blah"
REM _Text will be blah"blah"blah
REM Text will be blah^"blah^"blah
Other characters that could cause you errors (you can solve it with the above solution) are:
\ & | > < ^
In a windows batch shell (command) double quote are escape with ^ on standard command line BUT with a double double quote inside a double quoted string
echo Hello ^"Boy^"
echo "Hello ""Boy"""
(remark: second line will produce the external surrounding double quote in the output also)