19

When writing a Bash script you can use brace expansion to quickly generate lists:

Bash Brace Expansion

What is the simplest way to generate a similar list in Powershell? I can use the .. or , operators to generate an array, but how can I prefix the items with a static string literal?

PS C:\Users\gb> 1..5
1
2
3
4
5

PS C:\Users\gb> "test"+1..5
test1 2 3 4 5

PS C:\Users\gb> "test","dev","prod"
test
dev
prod

PS C:\Users\gb> "asdf"+"test","dev","prod"
asdftest dev prod
Greg Bray
  • 14,929
  • 12
  • 80
  • 104

3 Answers3

25
PS C:\> "test","dev","prod" | % { "server-$_" }
server-test
server-dev
server-prod
PS C:\> 1..5 | % { "server{0:D2}" -f $_ }
server01
server02
server03
server04
server05
PS C:\> 1..5 | % { "192.168.0.$_" }
192.168.0.1
192.168.0.2
192.168.0.3
192.168.0.4
192.168.0.5

Note that % is an alias for the ForEach-Object cmdlet.

Bill_Stewart
  • 22,916
  • 4
  • 51
  • 62
10

I'm hoping to be proven wrong here, but I don't believe there is a way to do it exactly like with bash, or with as few keystrokes.

You can iterate over the list by piping it through a foreach-object to achieve the same result though.

1..5 | foreach-object { "test" + $_ }

Or using the shorthand:

1..5 | %{"test$_"}

In both cases (% is an alias for foreach-object), the output is:

test1
test2
test3
test4
test5

Note: if you're building this into a script for publishing/distribution/reuse, use the more verbose foreach-object, not the shorthand % - for readability.

alroc
  • 27,574
  • 6
  • 51
  • 97
  • `1..5 | %{ "test$_" }` is even shorter still. – Lance U. Matthews Apr 25 '13 at 19:02
  • Correct you are - edited my code. I really need to break that concatenation habit. – alroc Apr 25 '13 at 19:05
  • Yeah I thought about just using for each, but it was a bit too verbose. `1..5 | %{"server{0:00}" -f $_}` is short enough that I'll probably just use that unless someone can think of a better solution. Thanks! – Greg Bray Apr 25 '13 at 19:06
  • `foreach ($x in $y) {stuff}` does get verbose, but for some things it's the way to go (and would be valid here). In this case, `foreach-object` with the pipeline is much less verbose. – alroc Apr 25 '13 at 19:08
3

I have a way to do it using int's tostring method. The '000' at the end is a special format code. It always pads to the right number of zeros. You can also use wildcards with method names like t*g if you really want to be terse and mysterious.

1..10 | % tostring computer000

computer001
computer002
computer003
computer004
computer005
computer006
computer007
computer008
computer009
computer010


1..10 | % t*g 192\.168\.1\.0

192.168.1.1
192.168.1.2
192.168.1.3
192.168.1.4
192.168.1.5
192.168.1.6
192.168.1.7
192.168.1.8
192.168.1.9
192.168.1.10

'x' is also a format code for hex printing.

10..15 | % tostring x

a
b
c
d
e
f

There's always -replace, which also works on arrays. '^' is regex for 'beginning of line'. Use '$' instead for 'end of line'.

(echo test dev prod) -replace '^','server-'

server-test
server-dev
server-prod

Hah, I never tried this before.

(echo test dev prod) -replace (echo ^ server-)

server-test
server-dev
server-prod

Maybe they could do that brace expansion in powershell 8...

js2010
  • 23,033
  • 6
  • 64
  • 66