1

%x:~12,3% Returns 3 characters starting at the 12:th character in x variable. What I have been trying to accomplish is using variables instead of 12 and 3. Let's say y=12 and z=3. Then, you can't use %x:~%y%,%z%%, because CMD will think %x:~% is a variable.

What you can do is set var=%%x:~%y%,%z%%%. This will expand the inside variables y and z, but not x, so that the value of var is %x:~12,3%. The remaining task at hand now is to finally expand %x:~12,3%. I have been trying to append echo in the beginning so that var=echo %x:~12,3%. If at the commandline or in a batch file you now use %var%, this should execute the echo command, and expand the succeeding expression, but it doesnt, instead echo %x:~12,3% results in simply %x:~12,3% being printed to the screen, unexpanded.

I was thinking that maybe if you set var to %x:~12,3%, then echo it and pipe the output into another ECHO command or SET command that the expression would be expanded, but it seems that ECHOand SETdoesn't accept data being piped into it at all?

How can I make this work?

Alpha_Pi
  • 383
  • 2
  • 13
  • 1
    This type of management is fully explained at: http://stackoverflow.com/questions/10166386/arrays-linked-lists-and-other-data-structures-in-cmd-exe-batch-script/10167990#10167990 – Aacini Feb 21 '16 at 04:39
  • Really, where exactly? I looked at that page but couldn't find anything on using variables to specify part of a string to extract. – Alpha_Pi Feb 21 '16 at 07:47
  • As I said, this _type of management_ is explained at that link, that is, how to use the value of _another variable_ in the expansion of the original one. See [my answer](http://stackoverflow.com/questions/35532216/cmd-piping-echo-to-set-expanding-variables-in-variables/35538235#35538235) below. – Aacini Feb 21 '16 at 15:53
  • How is this linked to pipes as mentioned in the question title? – aschipfl Mar 14 '16 at 22:06

3 Answers3

3

I copied the entire text below from this answer; I just changed the names of variables and particular examples to match the ones of this question:

%x:~12,3% returns 3 characters starting at the 12:th character in x variable. What I have been trying to accomplish is using variables instead of 12 and 3. Let's say y=12 and z=3.


If you want to use another variables for substring position and lenght, then you must know that the replacement of variables enclosed in percents by their values is parsed from left to right; this mean that: %x:~%y%,%z%% don't give the desired result because it mean: show the value of x:~ variable, followed by y, followed by the value of , variable, etc.

To solve this problem you must use Delayed Expansion, that is, insert setlocal EnableDelayedExpansion command at beginning, enclose substring variables in percents, and enclose the original variable in exclamation marks:

setlocal EnableDelayedExpansion
set x=0123456789ABCDEF
set y=12
set z=3
set var=!x:~%y%,%z%!

You may also use parameters of FOR commands as indexes: for /F "tokens=1,2" %%i in ("%y% %z%") do set var=!x:~%%i,%%j!.

To get the value of a substring when the index change inside FOR/IF enclose the variable in double percents and precede the command with call. For example, to show a substring at a random y position between 0 and 12 and lenght z:

if %some% == %test% (
   set /A y=!random! %% 13
   call echo %%x:~!y!,%z%%%
)

You may also use this method outside parentheses in order to avoid the Delayed Expansion:

call echo %%x:~%y%,%z%%%

Another way to achieve previous process is using an additional FOR command to change the delayed expansion of the index by an equivalent replaceable parameter, and then use the delayed expansion for the original variable. This method run faster than previous CALL:

if %some% == %test% (
   set /A y=!random! %% 13
   for %%y in (!y!) do echo !x:~%%y,%z%!
)
Community
  • 1
  • 1
Aacini
  • 65,180
  • 12
  • 72
  • 108
  • The two last methods you describe for use within `IF` and `FOR` parentheses does not seem to be necessary according to my testing. My testing shows that in your two above examples, using `ECHO !x:~%y%,%z%!` would work fine. – Alpha_Pi Feb 22 '16 at 03:08
  • The description at the [original answer](http://stackoverflow.com/questions/10166386/arrays-linked-lists-and-other-data-structures-in-cmd-exe-batch-script/10167990#10167990) is a general one that covers all possible aspects of this management. If you don't need some of these points, just don't use they (perhaps you will need they later). If you think this answer is useful, you may click on its check-mark and upvote it. Thanks! – Aacini Feb 22 '16 at 04:56
1

You need to enable delayed expansion.

@echo off
setlocal enabledelayedexpansion

set string=1234567890abcdef
set substring_start=12
set substring_length=3

set substring=!string:~%substring_start%, %substring_length%!
set command=echo !substring!

!command!
pause
SomethingDark
  • 13,229
  • 5
  • 50
  • 55
  • You don't happen to know why EnableDelayedExpansion doesn't work directly on the command line? – Alpha_Pi Feb 21 '16 at 07:46
  • @user504882 - it's not intended to. You can't use the `!var!` naming scheme on the command line. IMHO, you shouldn't be setting variables on the command prompt at all. – SomethingDark Feb 21 '16 at 07:57
  • 5
    @user504882 Delayed expansion is disabled per default at the command line, but it can be enabled when you start with `cmd.exe /V:on` or when you change the registry key `HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\DelayedExpansion` – jeb Feb 21 '16 at 10:12
1
@ECHO OFF
SETLOCAL

SET "x=abcdefghijklmmopqrstuvwxyz"

SET /a start=12
SET /a length=3

CALL SET "var=%%x:~%start%,%length%%%"
ECHO var=%var%
CALL echo %%x:~%start%,%length%%%

SETLOCAL ENABLEDELAYEDEXPANSION
SET /a start=6
SET /a length=4

SET "var=!x:~%start%,%length%!"
ECHO var=%var%
echo !x:~%start%,%length%!

GOTO :EOF

Two methods - the first in standard mode and the second using delayedexpansion. There are hundreds of examples on SO about delayedexpansion.

Magoo
  • 77,302
  • 8
  • 62
  • 84
  • The problem with `CALL SET` is that it starts a new instance of CMD running which makes it much slower. – Alpha_Pi Feb 22 '16 at 02:52
  • @user504882 No, `CALL` doesn't start a new instace, normally it's slow but it can be fast when you use `set pathext=:`. Btw. `FOR /F` starts a new instance, a pipe would start two new instances. – jeb Feb 27 '16 at 06:04