technique: string builder in batch

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
carlos
Expert
Posts: 503
Joined: 20 Aug 2010 13:57
Location: Chile
Contact:

technique: string builder in batch

#1 Post by carlos » 10 Feb 2014 18:38

I'm thinking about environment variables.
When you set a environment variable cmd sort all the the environment variable block.
Because this, I think that if need concatenate a string using this:

Code: Select all

set "line="
set "line=%line%string1"
set "line=%line%string2"
set "line=%line%string3"


cmd do 4 enviroment block sort (using all the environment variable names).

I want for avoid this. Then I found a way for save variables without use a file, keeping it in memory, using doskey.

Look this code (I use none set command for the concatenation):

Code: Select all

@echo off

(doskey concat==)

for %%# in (
"this"
"is"
"a"
"string"
) do for /f "tokens=1* delims==" %%a in (
'doskey /macros ^| findstr "^concat="'
) do (doskey concat=%%b%%~#)


rem display result
doskey /macros | findstr "^concat="

pause
Last edited by carlos on 10 Feb 2014 21:23, edited 1 time in total.

carlos
Expert
Posts: 503
Joined: 20 Aug 2010 13:57
Location: Chile
Contact:

Re: technique: string builder in batch

#2 Post by carlos » 10 Feb 2014 23:16

After test, I found that set is more speedy because is a internal command, and doskey a external command.


The slow part is access to the content of macro variable, using for /f pipe.
Save is fast, but access to the content is slow.

But, I think, that save variables in the macro section, can be useful for other thing.

carlos
Expert
Posts: 503
Joined: 20 Aug 2010 13:57
Location: Chile
Contact:

Re: technique: string builder in batch

#3 Post by carlos » 10 Feb 2014 23:27

I found a way of avoid the findstr part.

The idea is use a id that is unused. In this case: the id is "id". With that way: the id block have only 1 variable.

Code: Select all

@echo off

(doskey /exename=id concat==)

for %%# in (
"this"
"is"
"a"
"string"
) do for /f "tokens=1* delims==" %%a in (
'doskey /m:id'
) do (doskey /exename=id concat=%%b%%~#)


rem display result
doskey /m:id

pause



Edit: replaced /macros by /m

carlos
Expert
Posts: 503
Joined: 20 Aug 2010 13:57
Location: Chile
Contact:

Re: technique: string builder in batch

#4 Post by carlos » 11 Feb 2014 00:12

I found a new utility for saving variables with doskey

For example:
if we use disable delayed expansion and call to function that use setlocal enabledelayed expansión, we can save the result like a global variable:

example:

Code: Select all

@echo off

setlocal disabledelayedexpansion

call :clean
for /f "tokens=1* delims==" %%a in (
'doskey /m:clean') do echo(%%b


pause
goto :eof

:clean
setlocal enabledelayedexpansion
doskey /exename=clean result=abc
endlocal
goto :eof

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: technique: string builder in batch

#5 Post by Ed Dyreen » 17 Feb 2014 03:13

carlos wrote:I found a new utility for saving variables with doskey

For example:
if we use disable delayed expansion and call to function that use setlocal enabledelayed expansión, we can save the result like a global variable:

example:

Code: Select all

@echo off

setlocal disabledelayedexpansion

call :clean
for /f "tokens=1* delims==" %%a in (
'doskey /m:clean') do echo(%%b


pause
goto :eof

:clean
setlocal enabledelayedexpansion
doskey /exename=clean result=abc
endlocal
goto :eof
good idea, I created 3 functions, passing variables over endlocal is very easy like this :D

Code: Select all

setlocal
( %setDosKeyMacro_% testMacro_ ) %= transfer variable to doskey =%
endlocal
( %getDosKeyMacro_% testMacro_ ) %= restore variable from doskey =%
( %runDosKeyMacro_% testMacro_, " this, works, ""Thi^^ s^! work^^ s^!"" " ) %= restore variable from doskey and execute =%

Code: Select all

setDosKeyMacro_(testMacro_)
  data: 'for %? in (1,2) do if %?==2 (set ║=!*:º=º0!
set ║=!║:"=""!
set "║=!║:^=^^^^!"&call set "║=%^║:^!=º#^!%"&set "║=!║:º#=^^^!"
set ║=!║:""="!
set ║=!║:*=\*!
set ║=!║:\*=º4!
set ║=!║:?=º6!
set ?=&for %? in (!║!) do set ?=!?!ª%?
if "!?!"=="ª^^^!" set ?=###""
set ?=!?:º6=?!
set ?=!?:º4=*!
set ?=!?:º0=º!)&for /f "tokens=1-26delims=ª" %a in ("!?:~3!") do (echo(&<nul set
/p= a=%~a!_
echo(&<nul set/p= b=%~b!_
echo(&<nul set/p= c=%~c!_
endlocal)else setlocal enableDelayedExpansion&set *=^^^!'
 [ok:0]

 runDosKeyMacro_(testMacro_: this, works, "Thi^ s! work^ s!" )
  call: testMacro_,  this, works, "Thi^ s! work^ s!"
 [ok:0]
 a=this_
 b=works_
 c=Thi^ s! work^ s!_
 endoftest Druk op een toets om door te gaan. . .
But I failed to eleminate the call to a generic function ( command variables need percent expansion )

Code: Select all

(
   %$macro%%$p%
)

carlos
Expert
Posts: 503
Joined: 20 Aug 2010 13:57
Location: Chile
Contact:

Re: technique: string builder in batch

#6 Post by carlos » 17 Feb 2014 04:21

thanks.
I think that for avoid confussions is better use the same id for id and variable name, like this in this case the id is clean and the variable names is clean:

Code: Select all

@echo off

setlocal disabledelayedexpansion

call :func
for /f "tokens=1* delims==" %%a in (
'doskey /m:clean') do echo(%%b


pause
goto :eof

:func
setlocal enabledelayedexpansion
doskey /exename=clean clean=abc
endlocal
goto :eof

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: technique: string builder in batch

#7 Post by Ed Dyreen » 19 Feb 2014 10:38

I did some timeing on executing a dosKey compressed macro;

Code: Select all

 original uncompressed;
  len=3840_
 time=00:00:00,40_

 dosKey compressed;
  len=546_
 time=00:00:01,44_

 restored uncompressed;
  len=3840_
 time=00:00:00,43_
 endoftest Druk op een toets om door te gaan. . .
after the macro has been transferred it gets assigned a generic macro which does a lookup of itself in doskey memory then loads, executes and clears the variable. The stored macro needs one generic function call for for loading ( if return to disabledelayed is enabled ) and one for executing ( percent expansion to run command ).

The macro runs slower after compression but some environmental memory is saved.

There is a coding that needs to be done, doskey does not handle double quotes well, it will replace """" with """ corrupting the value. I have no idea why this happens or if this is by design.

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: technique: string builder in batch

#8 Post by Ed Dyreen » 23 Feb 2014 08:03

Found an additional complication;

Code: Select all

doskey.EXE /exename=m _= leadAndTrailSpace 
for /f delims^^=^^ eol^^= %%r in ( 'doskey /m:m' ) do echo. &<nul set /p "=#%%r#"

Code: Select all

#_=leadAndTrailSpace #
Similar to the set command on win7, any leading spaces are removed !, trailing spaces are preserved.

Code: Select all

doskey.EXE /exename=m _=_ leadingSpace
doskey /m:m
works as expected

Post Reply