• This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn more.

How To: Create Dynamic Variable Names in Scripts

B

Brandon Shell

#1
Goal:
-----
I want to create x number of groups. These groups will have a list of
servers. I split these servers in groups by name. What I would like is for
this function to be dynamic. I hope the example will make my goal clear.

Example:
---------
This is a very simple example... I am looking at creating 40+ groups... it
gets to be ALOT of duplicate code.

# This is what works now
Function Create-Groups {
param([system.array]$servers)
# this is where I would like to be more dynamic
$list1 = @()
$list2 = @()
$list3 = @()
$list4 = @()
$list5 = @()
foreach($server in $servers) {
if ($Server -match ".*ver1.$") {$list1 += $server}
elseif($Server -match ".*ver2.$") {$list2 += $server}
elseif($Server -match ".*ver3.$") {$list3 += $server}
elseif($Server -match ".*ver4.$") {$list4 += $server}
elseif($Server -match ".*ver5.$") {$list5 += $server}
}
# This is where I would like to be more dynamic
$global:group1 = $list1
$global:group2 = $list2
$global:group3 = $list3
$global:group4 = $list4
$global:group5 = $list5
}

Problem:
---------
Now if I wanted to make 10 groups instead of 5... I have create 5 more
arrays and global variables. I would like to do something like:

# this of course fails... is there a way I can do this?
$i = 1
while($i -lt 21) {
$list$i = @()
++$i
}
 

My Computer

?

=?Utf-8?B?U3VuZyBNIEtpbQ==?=

#2
"Brandon Shell" wrote:
> # this of course fails... is there a way I can do this?
> $i = 1
> while($i -lt 21) {
> $list$i = @()
> ++$i
> }

You can use "Invoke-Expression" cmdlet to create variables dynamially

foreach ($i in (1..21)) {
Invoke-Expression ('$`{list' + $i + '`} = @()')
}

Have fun~
--
Sung M Kim

Please don''t bother me with spam...
 

My Computer

B

Brandon Shell

#3
Thanks
"Sung M Kim" <SungMKim@discussions.microsoft.com> wrote in message
news:0A7D67F1-A612-46C3-A7CC-A5075012EFB0@microsoft.com...
> "Brandon Shell" wrote:
>> # this of course fails... is there a way I can do this?
>> $i = 1
>> while($i -lt 21) {
>> $list$i = @()
>> ++$i
>> }

> You can use "Invoke-Expression" cmdlet to create variables dynamially
>
> foreach ($i in (1..21)) {
> Invoke-Expression ('$`{list' + $i + '`} = @()')
> }
>
> Have fun~
> --
> Sung M Kim
>
> Please don''t bother me with spam...
>
 

My Computer

?

=?Utf-8?B?Um9tYW4gS3V6bWlu?=

#4
Yes, it is possible, but I would double think before using this approach. I
am just curious, why not to use, say, global hash tables with keys like
'ver1.$', 'ver2.$', etc. for servers, lists etc.?

--
Thanks,
Roman
 

My Computer

B

Brandon Shell

#5
Because I want to pipe the list to functions.

Example:
group1 | Check-Something | fix-problem

"Roman Kuzmin" <RomanKuzmin@discussions.microsoft.com> wrote in message
news:EDCBA044-6C0B-4361-96CC-37961F4B6589@microsoft.com...
> Yes, it is possible, but I would double think before using this approach.
> I
> am just curious, why not to use, say, global hash tables with keys like
> 'ver1.$', 'ver2.$', etc. for servers, lists etc.?
>
> --
> Thanks,
> Roman
>
 

My Computer

?

=?Utf-8?B?Um9tYW4gS3V6bWlu?=

#6
I definitely do not criticize.

Suppose your lists are in a hash $groups with keys like 1, 2, ‘ver5.$’ and
etc. For any <key>, i.e. group, you can do this:

$group[<key>] | Check-Something | fix-problem

No problem. For example if you want to process 3 groups 1, 2, ‘ver5.$’:

1, 2, ‘ver5.$’ | % {$group[$_]} | Check-Something | fix-problem

Suppose now a list of groups for a particular task is defined as an array
$ToDo; it is as easy as before:

$ToDo | % {$group[$_]} | Check-Something | fix-problem

Do you know how to do the same with your approach? If you know the answer
and like it then this approach is good for you.

--
Thanks,
Roman
 

My Computer

A

Adam Milazzo

#7
Brandon Shell wrote:
> Goal:
> -----
> I want to create x number of groups. These groups will have a list of
> servers. I split these servers in groups by name. What I would like is for
> this function to be dynamic. I hope the example will make my goal clear.


I wouldn't use invoke-expression. It's somewhat ugly.

I'd use the cmdlets designed for the purpose: new-variable,
set-variable, and get-variable (nv, sv, and gv).

nv "var.$foo"
sv "var.$foo" "value $i"
gv "var.$foo"

In place of string interpolation, you can use subexpressions:

nv ("var." + $nextVar)

You can also specify the value at creation time:

nv name value

-- Adam
 

My Computer

J

Jouko Kynsijärvi

#8
Sung M Kim wrote:
> "Brandon Shell" wrote:
>> # this of course fails... is there a way I can do this?
>> $i = 1
>> while($i -lt 21) {
>> $list$i = @()
>> ++$i
>> }

> You can use "Invoke-Expression" cmdlet to create variables dynamially
>
> foreach ($i in (1..21)) {
> Invoke-Expression ('$`{list' + $i + '`} = @()')
> }


Another, simpler, way is to use the new-variable cmdlet:

foreach ($i in (1..21)) {
new-variable "list$i" @()
}
 

My Computer

B

Brandon Shell

#9
I will take a look. You way does have some potential. My only concern is
that most of scripts are wrappers for people... that... hmmm... are less
than brilliant.

Im trying to keep the input as little and brainless as possible.

"Roman Kuzmin" <RomanKuzmin@discussions.microsoft.com> wrote in message
news:165DEFC0-FACA-4258-A531-A44ADE1FD1E6@microsoft.com...
>I definitely do not criticize.
>
> Suppose your lists are in a hash $groups with keys like 1, 2, 'ver5.$' and
> etc. For any <key>, i.e. group, you can do this:
>
> $group[<key>] | Check-Something | fix-problem
>
> No problem. For example if you want to process 3 groups 1, 2, 'ver5.$':
>
> 1, 2, 'ver5.$' | % {$group[$_]} | Check-Something | fix-problem
>
> Suppose now a list of groups for a particular task is defined as an array
> $ToDo; it is as easy as before:
>
> $ToDo | % {$group[$_]} | Check-Something | fix-problem
>
> Do you know how to do the same with your approach? If you know the answer
> and like it then this approach is good for you.
>
> --
> Thanks,
> Roman
>
 

My Computer

?

=?Utf-8?B?U3VuZyBNIEtpbQ==?=

#10
"Jouko Kynsijärvi" wrote:
> Another, simpler, way is to use the new-variable cmdlet:
>
> foreach ($i in (1..21)) {
> new-variable "list$i" @()
> }


That's brilliant ;)
This is the second time that I overlooked "*-Variable" cmdlets... as was the
case when I needed to create a constant variable ;p
--
Sung M Kim
 

My Computer

?

=?Utf-8?B?Um9tYW4gS3V6bWlu?=

#11
"Brandon Shell" wrote:
> I will take a look. You way does have some potential. My only concern is
> that most of scripts are wrappers for people... that... hmmm... are less
> than brilliant.


I agree. But, IMO, for those people it is more natural to operate with
*names* (of groups), not *variables* (associated with groups). Thus, scripts
(wrappers for those people) should be designed to take group names as input.
Moreover in outside world there are names only. If you are about to run your
script from cmd - what are you going to pass there as input/arguments?

Besides, group names are arbitrary, variable names are not (not so easy).
How are you planning to iterate through all currently defined groups?
Get-Variable group* | …? Then:

*) ‘Names’ of you groups are forced to be like groupX (+ limitations for
‘normal’ variable names);
*) You have to take care of not using variables $groupX for other purposes.

Finally, do not forget that number of variables is limited by
$MaximumVariableCount. You are going to use at least 40 of them; perhaps it
is not too much for this particular task but for other tasks with ‘dynamic
variable names’ this approach may be also painful just because of this
limitation.

--
Thanks,
Roman
 

My Computer

B

Brandon Shell

#12
I used names. We (my group) organize our servers (300+) into groups for
maintainance. My goal is to create Global variables for each group. My
delima is as we add more and more servers the number of groups change. I
would like to set one variable (the counter) and re-run the script to
add/subtract groups as needed. For my purpose having groups named $group'x'
is acceptable.

Example: I tell Joe OPS, "Hey, Can you do an App Check on Group 3?" He says
"Sure." All he has to do is:
PS> $group3 | AppCheck-Run
Server30 [PASSED]
Server31 [PASSED]
Server32 [FAILED]
Server33 [PASSED]

All Joe OPS has got to give me is the results. Then I say... "Can you
Publish Group 3." $group3 | Publish-Server

I do appreciate your suggestion and actually all the feedback you give on
these forums.

p.s. Thanks for reminding me about the variable limit... I did completely
forget about that.

"Roman Kuzmin" <RomanKuzmin@discussions.microsoft.com> wrote in message
news:8B5EE29A-314B-4B07-9B1B-8FA071C0BE13@microsoft.com...
> "Brandon Shell" wrote:
>> I will take a look. You way does have some potential. My only concern is
>> that most of scripts are wrappers for people... that... hmmm... are less
>> than brilliant.

>
> I agree. But, IMO, for those people it is more natural to operate with
> *names* (of groups), not *variables* (associated with groups). Thus,
> scripts
> (wrappers for those people) should be designed to take group names as
> input.
> Moreover in outside world there are names only. If you are about to run
> your
> script from cmd - what are you going to pass there as input/arguments?
>
> Besides, group names are arbitrary, variable names are not (not so easy).
> How are you planning to iterate through all currently defined groups?
> Get-Variable group* | .? Then:
>
> *) 'Names' of you groups are forced to be like groupX (+ limitations for
> 'normal' variable names);
> *) You have to take care of not using variables $groupX for other
> purposes.
>
> Finally, do not forget that number of variables is limited by
> $MaximumVariableCount. You are going to use at least 40 of them; perhaps
> it
> is not too much for this particular task but for other tasks with 'dynamic
> variable names' this approach may be also painful just because of this
> limitation.
>
> --
> Thanks,
> Roman
>
 

My Computer

Users Who Are Viewing This Thread (Users: 1, Guests: 0)