8

I'm trying to run a batch file that accepts a string which includes a variable name. The variable will then be used in the batch file. For example...

C:\>test.bat user%num%

In the batch file...

set num=1
(This is where I need help... Somehow set domainusername=user1)
echo %domainusername%

set num=2
...

The idea is to allow the batch call to work in the same way regardless of where the variable name is. Examples..

C:\>test.bat %num%user
or
C:\>test.bat us%num%er

Edit:
I've already done a fair amount of research trying to make this work. The most promising idea that I tried was a for loop to recursively evaluate %1 (in the example). Unfortunately, I couldn't make it work. Hopefully this sparks some ideas for others.

Lodra
  • 147
  • 1
  • 2
  • 7

4 Answers4

7

Code:

@ECHO off
SET param=%1
SET num=1
CALL SET x=%param%
ECHO %x%

Output:

user1
Ωmega
  • 42,614
  • 34
  • 134
  • 203
  • My goodness... So much simpler than everything I was trying. CALL... it works perfectly. Thank you. – Lodra Apr 19 '12 at 18:23
  • I'd like to note here that this can be done more than once even. It's a perfect way to expand a string before executing the command. Thanks again – Lodra Apr 19 '12 at 18:27
  • @Aacini - Interesting. Thanks for sharing this. – Ωmega Apr 21 '12 at 17:44
  • @stackoverflow - `test.bat user^%num%` ... You can't escape a percent sign with a caret this way, I tried to explain it in my answer – jeb Apr 21 '12 at 20:48
  • @stackoverflow - Then try `set num=2` before calling the batch file, the output will be `user2` instead of `user1` – jeb Apr 21 '12 at 21:01
  • @stackoverlflow: But he wants to call the batch with `test user%num%` from the cmd-line and then there should be an output of `user1`, `user2`, ... `user` as I understand. Try to append the `num=2` in your batch in it will fail, if you call it more than once. It's a general problem of the cmd-line IMHO. – jeb Apr 21 '12 at 21:16
  • This turned into an interesting page. Sorry, was gone for the weekend. I actually intend to make the call from outside the cmd line (from powershell) and inside the command line (other batch files). In both situations, Jeb has the correct idea for output. I've got a simple plan for making this kind of batch file call from the command line... dump %num% into a temp variable, clear %num% of any value, and then call the subsequent batch files the same as from outside the cmd line. This will probably include a little trial and error though – Lodra Apr 23 '12 at 15:14
  • I should be a little more clear when I say "outside the cmd line". I mean that powershell will start a new instance of cmd.exe and immediately run the batch file in question. The point being that there won't be any local environment variables set. – Lodra Apr 23 '12 at 15:17
4

As I understand the OP, the answers of Aacini and stackoverflow are wrong.

The delayed expansion solution (of Aacini) can only work if num is defined before starting the batch, else %mnm% will never expand.

C:\>set "num="

C:\>myBatch.bat user%num%

results to the output of
user%num%

The other solution (of stackoverflow) works a bit better, but fails when num is defined

I added a second set num=2 to demonstrate it

@ECHO off
SET param=%1
SET num=1
CALL SET x=%param%
ECHO %x%

set num=2
CALL SET x=%param%
ECHO %x%

Calling it two times shows the problem

C:\>myBatch user%num%
user1
user2

C:\>myBatch user%num%
user2
user2

In the second run you got 2 two times, as the result is fixed at the startup of the batch.

It's a good idea to echo the content of %1 to see if the format-string is really there or if the %num% is already expanded.

As I understand the OP (It's possible that I don't understand it!), the question is about using a placeholder,
but this is tricky with percents, as it only works at the command line (not from another batch) and it only works if the variable isn't defined in that moment.
Because, if the variable is defined, then the %num% will expand immediatly and the content of %1 is user2 and not user%num% (assuming num=2).

That it sometimes works is only a side effect of the cmd-line parser, as it does not remove an undefined variable (as inside a batch file), instead an undefined variable expansion will not changed in any way.

echo "%thisIsUndefined%"  - from cmd-line this outputs `"%thisIsUndefined%"`
echo "%thisIsUndefined%"  - from a batch file this outputs `""`

But as side effect, there doesn't exists a way to escape a percent sign in cmd-line context.
There exists only a workaround for a pseudo escape.
mybatch user%num^%
It doesn't really escapes the percent, but mostly there will not exists a variable named num^.

Then the solution of stackoverlow would work, with:

myBatch user%num^%

But I would prefere the delayed expansion, mentioned by Aacini.
You would call the batch then with exclamation marks, instead of percents, normally this works good, as delayed expansion is per default disabled.

myBatch user!num!

The batch itself would look like this

@echo off
set "param=%1"
Setlocal EnableDelayedExpansion
set num=1
echo %param%
set num=2
echo %param%
jeb
  • 78,592
  • 17
  • 171
  • 225
1

Excuse me. I think I don't really understand what you want. However...

If you pass the name of a variable to a Batch file, you may assign a value to that variable directly this way:

set %1=Any value

If you want to get the value of such variable, you need to use Delayed Expansion: insert setlocal EnableDelayedExpansion command at beginning and enclose the variable name (the %1 parameter) in exclamation marks:

setlocal EnableDelayedExpansion
set varValue=!%1!

In your case, I guess you want to achieve something like this:

set num=1
set domainusername=!user%num%!
echo %domainusername%

but this does NOT use the %1 parameter as you said, so I don't know...

I hope it helps...

EDIT: Perhaps this post may be useful to you...

Addendum: After I had realized what the OP wants, this is my solution:

@ECHO off
setlocal EnableDelayedExpansion
SET param=%1
SET num=1
SET x=!param!
ECHO %x%

A delayed expansion execute faster than a CALL...

Community
  • 1
  • 1
Aacini
  • 65,180
  • 12
  • 72
  • 108
  • Yes, I've thought about using delayed expansion, but I couldn't make this work either. The tricky part here, is that %1 contains a string and the variable I need to use. So I don't know how I can make "set %1=value" work for me. Really cool though. I've never thought to do that – Lodra Apr 19 '12 at 17:06
  • 1
    Perhaps if you post a larger example with step-by-step values ("giving this... I want to get this... etc.) I may help you better – Aacini Apr 19 '12 at 17:13
  • Firstly, thank you. Secondly, I will try to expand the original question soon. – Lodra Apr 19 '12 at 17:22
  • OK. Remember to add a comment here as a notice after you had done that :) – Aacini Apr 19 '12 at 17:26
  • It's true: `A delayed expansion execute faster than a CALL`, but in this case the result is incorrect :-), as the `%num%` can't be expanded in any parser phase – jeb Apr 21 '12 at 21:05
0

As an afterthought, you might consider testing that variable before you decide it is actually there. Add this to the start of your program:

if %1.==. goto :usage_orwherever
RobW
  • 424
  • 2
  • 5