How to split string in a variable without loosing spaces? - string

how can i split the string
" This is a text with spaces "
that is in the variable "string"
into text parts without loosing the spaces ?
set string="# This is a text with spaces #"
should be split into
"# This"
" is"
" a"
" text"
" with"
" spaces #"
Using For /F "delims= " ... doesn't work because it eliminates all spaces.
Is there a 'simple' solution or can anyone explain how to parse the string character by character
so i can count up spaces to first character, then read all characters until next space and write
the counted spaces and the read characters together to a new/temp variable ??
thanks

Yeah, I don't really understand the # either. What is it about " spaces #" that makes it hold onto the trailing spaces, while all other elements keep the preceding but not the proceeding spaces?
Oh, well, effort spent in asking = effort spent in answering. Do with this what you will.
#if (#a==#b) #end /*
:: batch portion
#echo off
setlocal
call :split "# This is a text with spaces #"
exit /b
:split <string>
cscript /nologo /e:jscript "%~f0" "%~1"
goto :EOF
:: JScript portion */
WSH.Echo(WSH.Arguments(0).match(/\s*\S+/g).join('\n'));
Output:
#
This
is
a
text
with
spaces
#
Update
If you want the first + second, and the penultimate + ultimate elements joined, modify the JScript portion of the above script as follows:
:: JScript portion */
var m = WSH.Arguments(0).match(/\s*\S+/g);
m[0] = m.shift() + m[0];
m[m.length - 2] += m.pop();
WSH.Echo(m.join('\n'));
Output:
# This
is
a
text
with
spaces #
And if you want each element enclosed in quotation marks, change the last line as follows:
WSH.Echo('"' + m.join('"\n"') + '"');
Output:
"# This"
" is"
" a"
" text"
" with"
" spaces #"

I don't see a simple solution in batch, though of course if you can consider powershell or javascript you'll be working with a more appropriate toolset for string manipulation.
Sticking with the batch requirement, you can loop through character by character and "collect" your words with something like this:
#echo off
setlocal enabledelayedexpansion
set "string= This is a text with spaces "
set idx=0
set "word="
set "char="
set "lastchar= "
:loop
if "!string:~%idx%!" equ "" goto :eof
set char=!string:~%idx%,1!
if "%char%" equ " " (
if "%lastchar%" neq " " (
echo [%word%]
set word=%char%
) else (
set word=%word%%char%
)
) else (
set word=%word%%char%
)
set lastchar=%char%
set /a idx=%idx%+1
goto loop
This script uses batch's substring feature !string:~%idx%,1 to grab a single character from the string, incrementing idx with each loop. Then it's just a matter of processing the word (echo in this example) when the previous character was not a space and the current one is.
This writes out:
[ This]
[ is]
[ a]
[ text]
[ with]
[ spaces]
Note that I'm ignoring the # you had in your example because I don't understand where they fit in.

the trick is substituting the contiguous spaces by just one space and the rest by some arbitrary character. Assuming your string does not contain #s and that there are no more than 9 contiguous spaces, you can try this
set st=%st: = ########%
set st=%st: = #######%
set st=%st: = ######%
set st=%st: = #####%
set st=%st: = ####%
set st=%st: = ###%
set st=%st: = ##%
set st=%st: = #%
then you may parse with for /f and substitute back your #s by spaces
setlocal enabledelayedexpansion
for /f %%a in ("%st%") do (
set ss= %%a
echo !ss:#= !
)
note that set inside the parentheses block requires you to enable delayed expansion and to use the ! syntax (see HELP SET)
But this technique will only extract the first substring. To generalize, you need another trick, that is substituting the spaces into newlines so that the for /f will loop kinda line by line
note that in order to obtain a newline char you need to preserve the two blank lines after the set command
set nl=^
rem continue two lines down....
for /f %%a in ("%st: =!nl!%") do (
set ss= %%a
set ss=!ss:#= !
echo [!ss!]
)

Try this:
#echo off &setlocal enabledelayedexpansion
set "string=# This is a text with spaces #"
set string1=%string%
for %%i in (%string%) do (
set string1=!string1: %%i = "%%i" !
set /a strings+=1
)
set string1=#"%string1:~1,-1%"#
set string1=%string1:"= "%
for %%i in (%string1%) do (
set /a count+=1
set string2=%%i
set string2=!string2: "=!
set string2=!string2:"=!
if !count! equ 2 (
set $s1=!$s1!!string2!
)else if !count! equ %strings% (
set /a count-=1
call set $s!count!=%%$s!count!%%!string2!
) else set $s!count!=!string2!
)
for /f "tokens=1*delims==" %%i in ('set "$s"') do echo "%%j"
Output:
"# This"
" is"
" a"
" text"
" with"
" spaces #"

If I had to accomplish this obscure task, I would use a hybrid JScript/batch technique like in rojo's answer. However, I would use a REPL.BAT utility that I have already written. Assuming my REPL.BAT is in either the current folder, or else somewhere in the PATH, then the following will work:
#echo off
setlocal enableDelayedExpansion
set "string=# This is a text with spaces #"
:: Build an "array" of text parts
set cnt=0
for /f delims^=^ eol^= %%A in ('repl "([^ ])(?= )" "$1\n" xs string') do (
set /a cnt+=1
set "string!cnt!=%%A"
)
:: Print the array values
for /l %%N in (1 1 %cnt%) do echo string%%N=[!string%%N!]
But if I wanted a pure batch solution, I would use the fairly efficient method below:
#echo off
setlocal enableDelayedExpansion
set "string=# This is a text with spaces #"
:: Define LF to contain a single line feed character (0x0A)
set LF=^
:: Above 2 blank lines are critical - DO NOT REMOVE
:: Insert a line feed before every space
for %%n in ("!LF!") do set "string=!string: =%%~n !"
:loop Remove line feeds sandwiched by spaces
for %%n in ("!LF!") do set "string2=!string: %%~n = !"
if "!string2!" neq "!string!" (
set "string=!string2!"
goto :loop
)
:: Build an "array" of text parts: FOR /F splits the string at line feeds
set /a cnt=0
for /f delims^=^ eol^= %%A in ("!string!") do (
set /a cnt+=1
set "string!cnt!=%%A"
)
:: Print out the array values
for /l %%N in (1 1 %cnt%) do echo string%%N=[!string%%N!]
Both solutions above give the following output:
string1=[#]
string2=[ This]
string3=[ is]
string4=[ a]
string5=[ text]
string6=[ with]
string7=[ spaces]
string8=[ #]
Note that the FOR loop %%A expansion will corrupt the results if the string contains ! due to delayed expansion. This limitation can be eliminated with additional coding. All the other posted solutions that use a FOR loop suffer from this same limitation. (at least they did when I wrote this)

Related

In batch script, split only last string match in a variable

In a batch script, I need to split only the last string match in a variable in a loop until I no longer have the string match.
Input=Level1/Level2/Level3/Level4/LevelN
(where N can be any number)
Output:
Level1/LeveL2/Level3/Level4
Level1/LeveL2/Level3
Level1/Level2
Level1
I have tried the usual "for /f "delims=/"" loops, but they only output each split of the input variable on an individual line. Besides, the value of "N" can vary. So I can't set the number of tokens to a certain value.
Please help.
This site don't works that way. You must post some code and explain the problems you have with it. In this way you can understand the changes made to your own code. If you request us for code, any code, then you could receive one ("any code") like this:
#echo off
setlocal EnableDelayedExpansion
set "Input=Level1/Level2/Level3/Level4/LevelN"
:loop
set "Output="
set "part=%Input:/=" & set "Output=!Output!/!part!" & set "part=%"
set "Input=%Output:~1%"
if "%Input%" equ "~1" goto exitLoop
echo "%Input%"
goto loop
:exitLoop
Here is a nice recursive approach that makes use of the ~ modifiers, assuming that the input string is provided as a quoted ("") command line argument, which does not begin with /, does not contain two consecutive // and none of the characters ", \, *, ?, <, >:
#echo off
rem // Store argument in variable:
set "INPUT=%~1"
if not defined INPUT exit /B
rem /* Precede with `\` and replace each `/` by `\`, so the resulting string appears to
rem be an absolute path, which can be split by `~` modifiers of `for` variables;
rem the inner `for` loop resolves the split path and removes any `\.` suffix: */
for %%I in ("\%INPUT:/=\%") do for %%J in ("%%~pI.") do set "REST=%%~pnxJ"
rem // Revert replacement of every `/` by `\` and remove the previously preceded `\`:
set "REST=%REST:\=/%"
set "REST=%REST:*/=%"
rem // If there is a string left, output it and call this script recursively:
if defined REST (
setlocal EnableDelayedExpansion
echo(!REST!
endlocal
call "%~f0" "%REST%"
)
A more classical approach, just for fun...
#echo off
setlocal EnableDelayedExpansion
set "Input=Level1/Level2/Level3/Level4/LevelN"
rem Split the string, join it again and store partial results
set "aux="
set "n=0"
for %%a in ("%Input:/=" "%") do (
set "aux=!aux!/%%~a"
set /A n+=1
set "out[!n!]=!aux:~1!"
)
rem Show results in reverse order
set /A n-=1
for /L %%i in (%n%,-1,1) do echo !out[%%i]!
This is easily done with a regex in PowerShell. Since the regex is greedy be default, it will get everything up to the last SOLIDUS and store it in the $1 group.
SET "S=Level1/Level2/Level3/Level4/LevelN"
FOR /F "delims=" %%a IN ('powershell -NoL -NoP "'%S%' -replace '(.*/).*', '$1'"') DO (
SET "RESULT=%%a"
)
ECHO RESULT is set to %RESULT%
Revision:
This outputs all groups and not just the last one.
SET "S=Level1/Level2/Level3/Level4/LevelN"
FOR /F "delims=" %%a IN ('powershell -NoL -NoP -Command ^
"$a = '%S%'.Split('/'); " ^
"for ($i = $a.Count - 2; $i -ge 0; $i--) { $a[0..$i] -join '/' }"') DO (
ECHO %%a
)

Batch Trim Lines in Text File after Sub-String - REM Trim with Expansion

I am running Windows 10 Pro using batch files (open to using VBS and PS1 files) and I have a text file automatically exported by software that can look like this:
Sub_Group691_FE7IP11_2017-12-12.sldasm_bin/parts/Loft-Project.sldasm_bin/parts/Loft-Project...
Sub_Group691_FE7IP12_2017-12-12.sldasm_bin/parts/Loft-Project.sldasm_bin/parts/Loft-Project...
Sub_Group691_FE7IP13_2017-12-12.sldasm_bin/parts/Loft-Project.sldasm_bin/parts/Loft-Project...
Each line continues specifying sub-parts after the "..." and could contain "poison" characters. The Sub_Group part is pulled from the filename and can also contain "poison" characters.
What I am looking to do is export just the filename which is right at the beginning of each line, up to and including the first file extension, in this case ".sldasm." Everything to the right of the first instance of .sldasm should be trimmed.
What I have cobbled together so far from research on Stackoverflow is:
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "inputfile=C:\Scratch\ASMExport.txt"
SET "outputfile=C:\Scratch\InputFiles.txt"
(
FOR /f "usebackqdelims=" %%a IN ("%inputfile%") DO (
SET "currentline=%%a"
ECHO("!currentline:.sldasm=.sldasm & rem "!"
)
)>"%outputfile%"
GOTO :EOF
My problem lies with the "rem" line, which does not seem to work as intended either because of being within a FOR loop or because of needing to enable delayed expansion. It seems to be parsing the "& rem" as text, which looks to be because of the way delayed expansion works. What I get from the above lines is:
SubGroup691_FE7IP11_2017-12-12.sldasm" & rem "/bin/parts/Loft-Project.sldasm" & rem ""
SubGroup691_FE7IP12_2017-12-12.sldasm" & rem "/bin/parts/Loft-Project.sldasm" & rem ""
SubGroup691_FE7IP13_2017-12-12.sldasm" & rem "/bin/parts/Loft-Project.sldasm" & rem ""
I can use this same line outside the loop and without ENABLEDELAYEDEXPANSION like this:
#ECHO OFF
SETLOCAL
SET "inputstring=Sub_Group691_FE7IP11_2017-12-12.sldasm_bin/parts/Loft-Project.sldasm_bin/parts/Loft-Project"
SET "outputstring=%inputstring:.sldasm=.sldasm & rem "%"
echo %outputstring%
The output to that would give me what I am looking for:
Sub_Group691_FE7IP11_2017-12-12.sldasm
In searching, I am beginning to think that rem cannot be used in this way, and I must move to a token delimiter loop using a bogus delimiter.
I would be content in getting this to work and not worrying about "poison" characters in the filename by being diligent about naming files correctly.
Thank you for your help!
The & rem approach to truncate strings to the right cannot work with delayed expansion (!), it relies on normal/immediate expansion (%). This is because immediate expansion is done before commands (like rem) are recognised, but delayed expansion happens afterwards, so the rem command is never executed.
However, you could in the loop replace every .sldasm by a forbidden character like | and then split the string by a for /F loop, like this:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "InputFile=C:\Scratch\ASMExport.txt"
set "OutputFile=C:\Scratch\InputFiles.txt"
set "Extension=.sdlasm"
> "%OutputFile%" (
for /F usebackq^ delims^=^ eol^= %%A in ("%InputFile%") do (
set "CurrentLine=%%A"
setlocal EnableDelayedExpansion
set "CurrentLine=!CurrentLine:%Extension%=|!"
for /F "delims=|" %%B in ("!CurrentLine!") do (
endlocal
echo(%%B
setlocal EnableDelayedExpansion
)
endlocal
)
)
endlocal
exit /B
Delayed expansion is toggled so that no for variables become expanded when it is enabled, in order to avoid loss of or problems with exclamation marks.
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "filename1=%sourcedir%\q47788829.txt"
FOR /f "usebackqtokens=1delims=/" %%a IN ("%filename1%") DO (
FOR /f "tokens=1*delims=." %%b IN ("%%a") DO (
FOR /f "tokens=1*delims=_" %%d IN ("%%c") DO (
ECHO %%%%-a=%%~a %%%%-b=%%~b %%%%-c=%%~c %%%%-d=%%~d %%%%-e=%%~e ^<^<
)
)
)
GOTO :EOF
You would need to change the setting of sourcedir to suit your circumstances.
I used a file named q47788829.txt containing your data for my testing.
You should be able to assemble your required report data from the elements %%a..%%e displayed. All a matter of using tokens and delims constructively.
If your input is the text that you wrote, with the same structure, I think this batch should work and extract the names that you want quickly.
CODE:
#echo off
setlocal enabledelayedexpansion
set "inputFile=input.txt"
set "outputFile=result.txt"
for /f "delims=/ tokens=1" %%A in (%inputFile%) do (
set "tempFileName=%%A"
echo !tempFileName:~0,-4!>> %outputFile%
)
You only had to adjust the variables 'inputFile' and 'outputFile' to your needs.

replace unneeded spaces with commas in txt using batch

I have a text file that contains some information and looks like this:
7253 198760.294 533963.581
7373 198752.213 533954.046
739CT 198751.288 533952.902
In every line there are parameters that has spaces between them but the spaces (not tabs) are for ease or reading only.
I need it to look like this:
1550,168040.682,630305.751,
1575,168023.241,630287.837,
15964TS,168008.317,630272.508,
Here is my code:
#echo off
setlocal EnableDelayedExpansion
set LF=^
set "content="
for /f "delims=" %%x in (input.txt) do (
set "content=!content!%%x!LF!"
)
:loop
if defined content (
set "new=!content: = !"
if "!new!" neq "!content!" (
set "content=!new!"
goto :loop
)
)
if defined content if "!str:~0,1!" equ " " set "content=!str:~1!"
if defined content if "!str:~-1!" equ " " set "content=!str:~0,-1!"
echo(!content!
set string=!content! & echo !string: =,! > output.txt
endlocal
pause > null
It turns everything in one line and connects between everything without spaces.
Concatenation to a single string is dangerous, because of limited max string length. Better process each line on it's own:
(for /f "tokens=1-3" %%a in (infile.txt) do (
echo %%a,%%b,%%c,
))>outfile.txt
note: empty lines will be ignored (will get lost)

separating variable with a symbol into different parts

using batch, i want to be able to separate a variable into two or three parts, when there is a symbol dividing them. for example if i have the string which looks like this:
var1;var2;
how can i get var1 to become variable and var2 to become a different one.
Thanks in Advance
The best way to split a variable into an array (or as close to an array as Windows batch can imitate) is to put the variable's value into a format that can be understood by a for loop. for without any switches will split a line word-by-word, splitting at csv-type delimiters (comma, space, tab or semicolon).
This is more appropriate than for /f, which loops line-by-line rather than word-by-word, and it allows splitting a string of an unknown number of elements.
Here's basically how splitting with a for loop works.
setlocal enabledelayedexpansion
set idx=0
for %%I in ("%var:;=","%") do (
set "var[!idx!]=%%~I"
set /a "idx+=1"
)
The important part is the substitution of ; into "," in %var%, and enclosing the whole thing in quotation marks. Indeed, this is the most graceful method of splitting the %PATH% environment variable for example.
Here's a more complete demonstration, calling a subroutine to split a variable.
#echo off
setlocal enabledelayedexpansion
set string=one;two;three;four;five;
:: Uncomment this line to split %PATH%
:: set string=%PATH%
call :split "%string%" ";" array
:: Loop through the resulting array
for /L %%I in (0, 1, %array.ubound%) do (
echo array[%%I] = !array[%%I]!
)
:: end main script
goto :EOF
:: split subroutine
:split <string_to_split> <split_delimiter> <array_to_populate>
:: populates <array_to_populate>
:: creates arrayname.length (number of elements in array)
:: creates arrayname.ubound (upper index of array)
set "_data=%~1"
:: replace delimiter with " " and enclose in quotes
set _data="!_data:%~2=" "!"
:: remove empty "" (comment this out if you need to keep empty elements)
set "_data=%_data:""=%"
:: initialize array.length=0, array.ubound=-1
set /a "%~3.length=0, %~3.ubound=-1"
for %%I in (%_data%) do (
set "%~3[!%~3.length!]=%%~I"
set /a "%~3.length+=1, %~3.ubound+=1"
)
goto :EOF
Here's the output of the above script:
C:\Users\me\Desktop>test.bat
array[0] = one
array[1] = two
array[2] = three
array[3] = four
array[4] = five
Just for fun, try un-commenting the set string=%PATH% line and let the good times roll.
Tokens=1,2 does create the two for loop variables %%i and %%j& splits string in two parts, separated by the delimiter ;:
#echo off &setlocal
set "string=var1;var2;"
for /f "tokens=1,2 delims=;" %%i in ("%string%") do set "variable1=%%i" &set "variable2=%%j"
echo variable1: %variable1%
echo variable2: %variable2%
endlocal
pause
For a more "dynamic" method use this:
#echo off &setlocal enabledelayedexpansion
set "string=var1;var2;"
set /a count=0
for %%i in (%string%) do (
set /a count+=1
set "variable!count!=%%i"
)
echo found %count% variables
for /l %%i in (1,1,%count%) do (
echo variable%%i: !variable%%i!
)
endlocal
If you got only "one" appears, change the line
for /L %%I in (0, 1, %array.ubound%) do (
by
for /L %%I in (0, 1, !array.ubound!) do (

Batch file: How to replace "=" (equal signs) and a string variable?

Besides SED, how can an equal sign be replaced?
And how can I use a string variable in string replacement?
Consider this example:
For /F "tokens=*" %%B IN (test.txt) DO (
SETLOCAL ENABLEDELAYEDEXPANSION
SET t=is
SET old=%%B
SET new=!old:t=!
ECHO !new!
ENDLOCAL
)
:: SET new=!old:==!
Two problems:
First, I cannot use the variable %t% in !:=!.
SET t=is
SET old=%%B
SET new=!old:t=!
Second, I cannot replace the equal sign in the command line
SET new=!old:==!
I just created a simple solution for this myself, maybe it helps someone.
The disadvantage (or advantage, depends on what you want to do) is that multiple equal signs one after another get handled like one single equal sign. (example: "str==ing" gives the same output as "str=ing")
#echo off
set "x=this is=an test="
echo x=%x%
call :replaceEqualSign in x with _
echo x=%x%
pause&exit
:replaceEqualSign in <variable> with <newString>
setlocal enableDelayedExpansion
set "_s=!%~2!#"
set "_r="
:_replaceEqualSign
for /F "tokens=1* delims==" %%A in ("%_s%") do (
if not defined _r ( set "_r=%%A" ) else ( set "_r=%_r%%~4%%A" )
set "_s=%%B"
)
if defined _s goto _replaceEqualSign
endlocal&set "%~2=%_r:~0,-1%"
exit /B
As you have seen, you use the function like this:
call :replaceEqualSign in variableName with newString
The setlocal enableDelayedExpansion should be moved after your old=%%B assignment in case %%B contains !.
The "t" problem is easy to solve within a loop by using another FOR variable
For /F "tokens=*" %%B IN (test.txt) DO (
SET t=is
SET old=%%B
SETLOCAL ENABLEDELAYEDEXPANSION
for /f %%T in ("!t!") do SET new=!old:%%T=!
ECHO !new!
ENDLOCAL
)
There is no simple native batch solution for replacing =. You can iterate through the string, character by character, but that is slow. Your best bet is probably to switch to VBScript or JScript, or use a non-native utility.
If you really want to do this using pure Windows batch commands, there are a couple of interesting ideas at http://www.dostips.com/forum/viewtopic.php?t=1485
UPDATE: The latest version is here: https://github.com/andry81/contools (https://github.com/andry81/contools/tree/HEAD/Scripts/Tools/std/)
You can use some sequence to temporary replace special characters by placeholders like ?00, ?01, ?02 and ?03. I basically use these set of scripts:
replace_sys_chars.bat:
#echo off
rem Description:
rem Script to replace ?, !, %, and = characters in variables by respective
rem ?00, ?01, ?02 and ?03 placeholders.
setlocal DISABLEDELAYEDEXPANSION
set "__VAR__=%~1"
if "%__VAR__%" == "" exit /b 1
rem ignore empty variables
call set "STR=%%%__VAR__%%%"
if "%STR%" == "" exit /b 0
set ?01=!
call set "STR=%%%__VAR__%:?=?00%%"
set "STR=%STR:!=?01%"
setlocal ENABLEDELAYEDEXPANSION
set STR=!STR:%%=?02!
set "STR_TMP="
set INDEX=1
:EQUAL_CHAR_REPLACE_LOOP
set "STR_TMP2="
for /F "tokens=%INDEX% delims== eol=" %%i in ("/!STR!/") do set STR_TMP2=%%i
if "!STR_TMP2!" == "" goto EQUAL_CHAR_REPLACE_LOOP_END
set "STR_TMP=!STR_TMP!!STR_TMP2!?03"
set /A INDEX+=1
goto EQUAL_CHAR_REPLACE_LOOP
:EQUAL_CHAR_REPLACE_LOOP_END
if not "!STR_TMP!" == "" set STR=!STR_TMP:~1,-4!
(
endlocal
endlocal
set "%__VAR__%=%STR%"
)
exit /b 0
restore_sys_chars.bat:
#echo off
rem Description:
rem Script to restore ?, !, %, and = characters in variables from respective
rem ?00, ?01, ?02 and ?03 placeholders.
setlocal DISABLEDELAYEDEXPANSION
set "__VAR__=%~1"
if "%__VAR__%" == "" exit /b 1
rem ignore empty variables
call set "STR=%%%__VAR__%%%"
if "%STR%" == "" exit /b 0
setlocal ENABLEDELAYEDEXPANSION
set STR=!STR:?02=%%!
set STR=!STR:?03==!
(
endlocal
set "STR=%STR%"
)
set "STR=%STR:?01=!%"
set "STR=%STR:?00=?%"
(
endlocal
set "%__VAR__%=%STR%"
)
exit /b 0
Example:
#echo off
setlocal DISABLEDELAYEDEXPANSION
for /F "usebackq tokens=* delims=" %%i in ("test.txt") do (
set VALUE=%%i
call :PROCESS
)
exit /b 0
:PROCESS
if "%VALUE%" == "" exit /b 0
set "VALUE_=%VALUE%"
call replace_sys_chars.bat VALUE_
rem do variable arithmetic here as usual
if not "%VALUE_:?00=%" == "%VALUE_%" echo."%VALUE%" having ?
if not "%VALUE_:?01=%" == "%VALUE_%" echo."%VALUE%" having !
if not "%VALUE_:?02=%" == "%VALUE_%" echo."%VALUE%" having %%
if not "%VALUE_:?03=%" == "%VALUE_%" echo."%VALUE%" having =
rem restore it
call restore_sys_chars.bat VALUE_
echo "VALUE=%VALUE_%"
echo.---
test.txt:
111/222
AAA=BBB
CCC=%DDD%
EEE=!FFF!
FFF=?00?01?02?03
Result:
"VALUE=111/222"
---
"AAA=BBB" having =
"VALUE=AAA=BBB"
---
"CCC=%DDD%" having %
"CCC=%DDD%" having =
"VALUE=CCC=%DDD%"
---
"EEE=!FFF!" having !
"EEE=!FFF!" having =
"VALUE=EEE=!FFF!"
---
"FFF=?00?01?02?03" having ?
"FFF=?00?01?02?03" having =
"VALUE=FFF=?00?01?02?03"
---
Features:
You can continue use standard batch variable arithmetic between conversions
You can use character placeholders (?00, ?01, ?02, ?03) as plain variable values
Why not use Edlin? I could not find a way to do this with one initial file and no errors from Edlin, but just ignore them with NUL:.
Strangly, the TYPE %0 includes the whole file even if there's an end of file character between the = and !, using TYPE on the batch file after it has run will not work the same way.
#ECHO OFF
GOTO skip
1,1r=!
e
:skip
SET "new==old============="
ECHO %new% > %TEMP%\var.tmp
TYPE %0 > %TEMP%\edlin.tmp
EDLIN %TEMP%\var.tmp < %TEMP%\edlin.tmp > NUL:
SET /P newnew=<%TEMP%\VAR.TMP
ECHO %newnew%
ERASE %TEMP%\VAR.TMP
ERASE %TEMP%\VAR.BAK
ERASE %TEMP%\edlin.tmp
I was looking into this, because I needed to get rid of = in a string like "test=goingon"
I found that calling a next batchfile with test=goingon as parameters, I have parameters 1, "test" and 2, "goingon", in that batchfile.
So:
batchfile 1:
#echo off
call test2.bat test=goingon
batchfile2:
echo arg1: %1
echo arg2: %2
result:
arg1: test
arg2: goingon
I used Bosj's idea to come up with this. It works.
set s=Abra=Cadabra
echo now you see it %s%
call :ReplaceEqual %s%
echo now you don't %s%
exit /b
:ReplaceEqual
set s=%1_%2
exit /b
My answer from another post, but it applies here, too:
There is an alternative that is easier. Instead of passing in a value that contains an equals sign, try something like a colon instead. Then, through the ability to modify that value (the colon), you can convert it back into an equals. Here is an example:
#echo off
set VALUE1=%1
set VALUE2=%VALUE1::==%
echo value1 = %VALUE1%
echo value2 = %VALUE2%
When you run the batch file, call it like this:
C:\>myBatch name:someValue
The output would be:
value1 = name:someValue
value2 = name=someValue
If the name or value contains a space, you will have other issues to address, though. You will need to wrap the entire string in double quotes. But, then you have the issue of needing to get rid of them. This can also be handled, like this:
#echo off
cls
set PARAM=%1
set BASE=%PARAM:"=%
set PAIR=%BASE::==%
rem Either of these two lines will do the same thing - just notice the 'delims'
rem for /f "tokens=1,2 delims=:" %%a in ("%BASE%") do set NAME=%%a & set VALUE=%%b
rem for /f "tokens=1,2 delims==" %%a in ("%PAIR%") do set NAME=%%a & set VALUE=%%b
for /f "tokens=1,2 delims=:" %%a in ("%BASE%") do set NAME=%%a & set VALUE=%%b
echo param = %PARAM%
echo base = %BASE%
echo pair = %PAIR%
echo name = %NAME%
echo value = %VALUE%
When running this batch file like this:
C:\>myBatch "some name:another value"
The output will be:
param = "some name:another value"
base = some name:another value
pair = some name=another value
name = some name
value = another value
Hope that helps others in their quest to win the fight with batch files.
Mike V.

Resources