[Question]
  [
What general tips do you have for golfing in Windows PowerShell? I'm looking for ideas that can be applied to code golf problems in general that are at least somewhat specific to PowerShell (e.g. "remove comments" is not an answer). Please post one tip per answer.
—taken nearly verbatim from [marcog's question](https://codegolf.stackexchange.com/questions/54/tips-for-golfing-in-python).
  
[Answer]
Powers of 10 literals with scientific notation:
```
4e6 = 4000000
```
Powers of 2 literals:
```
4KB = 4096
4MB = 4194304
4GB = 4294967296
# TB and PB suffixes also exist, but less useful for golf.
```
Could come in handy.
[Answer]
If you need to run a loop, and you know *exactly* how many times it needs to run every time, consider piping an array of contiguous integers into `ForEach-Object` via the `%` alias instead of using `for`.
`for($x=1;$x-le10;$x++){`...`}`
vs
`1..10|%{`...`}`
[Answer]
You can skip spaces *a lot* in PowerShell. If it feels like it might not be needed, it quite possibly isn't. This is particularly useful in comparisons.
Example:
```
$x-eq$i-and$x-ne9
```
vs. 
```
$x -eq $i -and $x -ne 9
```
---
If you need to branch your script based on the result of a single test which may have multiple outcomes, `switch` can sometimes match or beat an if statement.
Example (switch vs. if/else - tie):
```
if($x%2-eq0){'even'}else{'odd'}
```
vs.
```
switch($x%2){0{'even'}1{'odd'}}
```
Or (switch vs. if/elseif/else - switch wins by 15):
```
if($x%2-eq0){'even'}elseif($x%2-eq1){'odd'}else{'error'}
```
vs.
```
switch($x%2){0{'even'}1{'odd'}2{'error'}}
```
If the switch is *actually* based on certain math results, like the modulo operation above, you can replace the switch entirely with an array. Here, it saves another 13 characters and is even shorter than the original two-option if/else statement. (Thanks to [Danko Durbic](https://codegolf.stackexchange.com/questions/12177/collatz-conjecture/15220?noredirect=1#comment29076_15220) for this bit.)
```
('even','odd','error')[$x%2]
```
If you will be using a particular command a lot, especially one without a pre-existing short-hand alias, set up a single-character alias early on.
Example:
```
nal g Get-Random;g 10;g 10;g 10
```
vs.
```
Get-Random 10;Get-Random 10;Get-Random 10
```
[Answer]
Encapsulating the command that defines a variable in parenthesis allows you to feed the variable's definition directly to other commands.
For example, you can set $x and then set $y based on the value of $x in one shot with this:
```
$y=($x=1)+1
```
Instead of this:
```
$x=1;$y=$x+1
```
You can set $h and output it with this:
```
($h='Hello World!')
```
Instead of this:
```
$h='Hello World!';$h
```
[Answer]
A switch can act like a loop, when given an array. For example:
```
$FooBarMeh='a','b','c'
switch ($FooBarMeh)
{
    'a'{'FOO'}
    'b'{'BAR'}
    default{'MEH'}
}
```
Will output:
> 
> FOO  
> 
>  BAR  
> 
>  MEH
> 
> 
> 
I'm not totally sure where this will be useful, but I expect it will be handy for someone some time.
[Answer]
Want to find the maximum or minimum of a collection of values? Tried
```
(...|measure -ma).Maximum
```
or
```
(...|measure -mi).Minimum
```
already?
Just sort and use the last or first item:
```
(...|sort)[-1]  # maximum
(...|sort)[0]   # minimum
```
[Answer]
Replace `[math]::pow` with multiplication. Instead of 
```
[math]::pow($a,$b)
```
you can write
```
"$a*"*$b+1|iex
```
This works for integer exponents >= 0.
[Answer]
# Shortening Property Names
Sadly, unlike parameters, properties/methods (anything accessed with a dot `.`) cannot usually be shortened down to its unambiguous form.
But certain cmdlets can operate on property names and take wildcards, and there are little-known parameter sets of `%` and `?` that can be useful.
Usually we pass in a scriptblock and refer to the item with `$_`, but there's another form of these that takes a property name, and it accepts a wildcard.
```
$o|select Le*  
$o|%{$_.Length}
```
With a property like `.Length` we can't use the v3 magic that would normally work on an array because `Length` is a property of the array itself, so the above two could be used to get the lengths of the individual members. The `select` comes in a little bit shorter.
But `%` can take a property name directly and return that value:
```
$a|% Length
```
Which can be shortened with wildcards. The wildcard must resolve to a single property (or method, more on that later), so it will throw a helpful error if it doesn't, indicating exactly which members it could resolve to.
In the case of `Length`, `Le*` is typically the shortest. Even on a single string, this method is 1 byte shorter than just using the property.
```
$a.Length                # 9   #(doesn't work on array)
$a|%{$_.Length}          # 15
$a|% Le*                 # 8
```
But depending on what you're doing with this, this can be worse. You can do `$a.Length*5` but to do it with the pipeline expression you'd have to wrap it `($a|% Le*)*5`; might still be worth it if it's against an array, but the point is it's not always appropriate as a straight substitution.
It works with methods too, and you can leave off the `()` which makes a full name the same length, but same restriction as above about sometimes having to wrap it. ~~The method must have an overload that takes no parameters~~ (you can pass arguments by placing them after the method name, which is really nice):
```
$a.ToUpper()             # 12
$a|% *per                #  9
```
With arguments:
```
'gaga'-replace'g','r'    # 21
'gaga'|% *ce g r         # 16
```
These aren't strictly the same in that the `-replace` operator does a regex replace, but if you're just doing a string replace, it can (now) be shorter to use the method; it helps that the strings are cmdlet arguments instead of method arguments so they don't need to be quoted.
## Where-Object Properties
`?` can take (partial) property names as well, and apply an "operator" to it (in the form of switch parameters). Again this can be shorter than using the standard `Where-Object` scriptblock approach if the property name is sufficiently long and unique.
```
$a|?{$_.Length-gt5}      # 19
$a|? Le* -GT 5           # 14
($a|% Le*)-gt5           # 14 - Lengths, not objs
```
[Answer]
Comparison operators work on collections of values by returning matching values:
```
1..5 -gt 2
```
will yield `3`, `4` and `5`. In some cases this can help to save an otherwise longer `|?{$_...}`.
`-match` is a comparison operator too.
[Answer]
Use aliases whenever possible. There are a bunch of useful ones:
```
?        Where-Object
%        ForEach-Object
gu       Get-Unique
sort     Sort-Object
iex      Invoke-Expression
```
[Answer]
Finding a sum the long way:
```
(...|measure -s).Sum
```
A shorter way:
```
...|%{$s+=$_};$s
```
And even shorter:
```
...-join'+'|iex
```
[Answer]
`for` loops can have anything between 0 and three statements in their header:
Endless loop:
```
for(){}
```
Loop with initialization:
```
for($n=0){}
```
Loop with initialization and end condition:
```
for($n=0;$n-lt7){}
```
In such cases the additional semicolons at the end may be omitted (it's explicitly stated in the [language specification](http://www.microsoft.com/download/en/details.aspx?id=9706), so it's not an implementation detail) in contrast to C-like languages which always require exactly three statements.
This also makes `while` a bit shorter. Compare
```
while(...){}
```
and
```
for(;...){}
```
With the added bonus that you can stick in a previous line (if there is one) into the `for` as well without extra cost (and even saving a character).
[Answer]
Semicolons and line breaks are interchangeable. Golfed code is often more readable if not jammed into a single line. And the length is still the same (provided you use U+000A as line break which PowerShell handles without problems).
[Answer]
The `Get` verb is implied. This can shorten any `Get-Frob` to just `Frob`. Frequent contenders are `date` or `random`.
Note that this *won't* work properly in some cases because you might have GNU utilities in your path (or other native programs that clash). Order of command lookup in that case seems to prefer the native program before it considers cmdlets with the `Get-` removed:
```
PS Home:\> date
Freitag, 15. November 2013 07:13:45
PS Home:\> $Env:Path += ';D:\Users\Joey\Apps\GnuWin32\bin'
PS Home:\> date
Fr Nov 15 07:14:13 W. Europe Standard Time 2013
```
[Answer]
If you are assigning an array that you know will only have two values, don't use indexing.
Something like this:
```
$a="apple","orange"
$a[0] # apple
$a[1] # orange
```
Can easily be turned into this:
```
$a,$o="apple","orange"
$a # apple
$o # orange
```
This can also be useful for if you just need to the first element of an array:
```
$a,$b=1..10
$a # 1
$b # 2..10
```
[Answer]
Casting to string:
```
[string]$x
```
vs.
```
"$x"
```
Casting to string like this can also be used to flatten an array of strings, instead of joining it:
```
$a = @('a','b','c')
$a -join ' '
```
vs.
```
$a = @('a','b','c')
"$a"
```
Casting a string to a numeric type:
```
[int]$x     [float]$x
```
vs.
```
+$x
```
Also very useful to know that PowerShell *always* takes the type of the left operand to determine the final type of an expression and conversions to apply:
```
'1'+2    -> '12'
1+'2'    -> 3
```
which can help determining where needless casts are.
[Answer]
Don't forget that you don't always need to provide the full name of a parameter, and some parameters are positional.
```
Get-Random -InputObject (0..10)
```
...can be trimmed to...
```
Get-Random -I (0..10)
```
...because "I", in this case, is enough to uniquely identify `InputObject` from the other valid parameters for this command.
You could trim it further to...
```
Get-Random (0..10)
```
...because `InputObject` is a positional parameter.
Piping is usually shorter than feeding objects as a parameter, especially when it can remove the need for parenthesis. Let's trim our random number generator further...
```
0..10|Get-Random
```
Also be on the lookout for other ways to accomplish the same thing, even if you can't change the command. For the above case, you could do this:
```
Get-Random 11
```
Or, incorporating [another suggestion](https://codegolf.stackexchange.com/a/778/9387)\*:
```
Random 11
```
\*\*Note: Omitting `Get-` from a command name can bloat the run time by about 50,000%. Not bad if you only need the command once, but be careful using it in long loops.\*
And that's how can knock a simple command down to a third of its size.
[Answer]
Automatic variables have booleans for True and False as `$true` and `$false` but you can get similar results using the logical not operator `!` and the integers 0 and 1( or any non-zero integer.) 
```
PS C:\Users\matt> !1
False
PS C:\Users\matt> !0
True
```
Near all PowerShell expressions can be evaluated as booleans. So as long as you are aware of how certain data is evaluated you can get booleans and never need to explicitly cast them. Be aware of the LHS value when doing these.
* Integer 0 is false and non-zero integers are evaluated to true.
* non-zero length strings are true and empty or null (and nulls themselves) strings are false.
There are other examples but you can easily test by doing a cast 
```
PS C:\Users\matt> [bool]@(0)
False
```
[Answer]
When using a number as an argument to an operator that would otherwise require a string, you can use the number directly. Compare
```
...-join'0'
```
vs.
```
...-join0
```
Works with `-split` as well. The argument is always converted to a string first.
[Answer]
Fake ternary operator. You can assign straight from an `if` statement:
```
$z=if($x-eq$y){"truth"}else{"false"}
```
But you can use a 2-element array and use the test to index into it. $falsey results get element 0, $truthy results take element 1:
```
$z=("false","true")[$x-eq$y]
```
NB. that this is really doing array indexing, and if the test results in a value which *can* be cast to an integer, you'll ask for an item outside the bounds of the array and get $null back, and will need to do `!(test)` to force cast the result to a bool, with the options reversed.
[ Edit: There's a genuine ternary operator in PowerShell 7+ in the C-language-style `cond ? 1 : 0` ]
[Answer]
Absolute value
With
```
$n=-123
```
Instead of
```
[math]::abs($n)
```
use
```
$n-replace'-'
```
Of course, the savings are cancelled if parentheses are needed.
[Answer]
If you need to silence errors, the obvious variant would be
```
try{ <# something that throws errors #> }catch{}
```
However, this is way too long. A shorter variant is to run the `try` block as a script block and just redirect the errors into an unset variable (`$null` would be the usual one, but that's still too long):
```
.{ <# something that throws errors #> }2>$x
```
This saves five valuable bytes (if not the world).
[Answer]
Use the `$ofs` [special variable](https://technet.microsoft.com/en-us/library/hh847768.aspx) to change the **O**utput **F**ield **S**eparator used when stringifying an array. Useful if you're needing to transform arrays to strings multiple times.
For example:
```
$a=1,2,3,4
$a-join',';$a-join','
$ofs=',';"$a";"$a"
```
Saves 2+*n* characters on the 2nd `-join`, where *n* is the length of the separator, and saves an additional 5+*n* for the 3rd `-join` and each thereafter.
[Answer]
## **Use `[bigint]` instead of `[Math]::floor`**
The `bigint` datatype is a numeric type that can store arbitrarily large numbers and holds no decimal values. It always floors when using `[bigint]::new()`.
A suffix for it was added in PowerShell core but using the `n` prefix rounds normally instead of floor which doesn't work for this.
Example:
```
[bigint](.9)        # 0
[bigint]3/4         # 0
[bigint](.1)        # 0
[bigint]1/4         # 0
[bigint]10.5        # 10
[bigint]100/3       # 33
(.9)n               # 1
3/4n                # 1
(.1)n               # 0
1/4n                # 0
10.5n               # 11
100/3n              # 33
```
[Answer]
`Invoke-Expression` and `Get-Random` can also get pipeline input instead of arguments.
For `iex` this allows to save parentheses on some expressions:
```
iex 1..5-join'+'   # won't work
iex(1..5-join'+')  # does work, but has extra parentheses
1..5-join'+'|iex   # doesn't need the parentheses
```
In case of `random` this allows a common case to be optimized a bit:
```
random -mi 10 31   # gets a random integer between 10 and 30
10..30|random      # much better :-)
(random 21)+10     # if needed in another expression that doesn't require extra
                   # parentheses
```
The latter way of using it simply selects an item from a list. The `-c` argument can be given to allow more than a single selection.
[Answer]
Consider storing repeated script blocks in variables, instead of using functions.
I was going to use this to save some characters in [my Rock, Paper, Scissors implementation](https://codegolf.stackexchange.com/a/15386/9387) before I realized that re-writing the function as a variable made even the variable unnecessary. This could still be useful for other scripts though, where you're actually running the same code multiple times.
```
function Hi{echo 'Hello, World!'};Hi
```
vs.
```
$Hi={echo 'Hello, World!'};&$Hi
```
[Answer]
Converting floating-point numbers to integers in PowerShell is a bit of a minefield. By default the conversion does [Bankers Rounding](http://c2.com/cgi/wiki?BankersRounding) which doesn't always trim off the decimal and leave the smaller whole number, or always round .5 up to the next number like people do casually, it rounds evens one way and odds another way - this can be surprising, e.g. 
```
PS C:\> [int]1.5
2
PS C:\> [int]2.5
2
```
and break codegolf calculations. Many other common languages do truncation-rounding, therefore golf questions often require truncation. You might reach for `[Math]::Floor()` as the next best thing, but beware this only behaves the same as truncation for positive numbers, but it takes negative numbers lower - further away from zero. `[Math]::Truncate()` is what you need to bring PS behaviour in line with other language's default rounding, but it's a lot of characters.
Regex replacing digits after the decimal point can help save a couple of characters:
```
[Math]::Truncate(1.5)
[Math]::Floor(1.5)
1.5-replace'\..*'
[Math]::Truncate($a)
[Math]::Floor($a)
$a-replace'\..*'
$a.split('.')[0]        # literal character split, not regex pattern split
```
[Answer]
### Use variables to store .NET names
As outlined by cogumel0 in [this answer](https://codegolf.stackexchange.com/a/148058/42963), you can use variables to store .NET type names. For example, changing
```
param($a)$a-[math]::pow(2,[math]::floor([math]::log($a,2)))
```
into
```
param($a)$a-($m=[math])::pow(2,$m::floor($m::log($a,2)))
```
saved 3 bytes in this example.
[Answer]
You can use `$s|% t*y` instead `[char[]]$s` to split a string to char array.
Given from [TessellatingHeckler's answer](https://codegolf.stackexchange.com/a/158441/80745): `% t*y` expands to `| ForEach-Object -Method ToCharArray` equiv. of `"$args".ToCharArray()`
For example, compare
```
$s|% t*y
```
and
```
[char[]]$s
```
and
```
$s.ToCharArray()
```
It's useful with `$args` especially: `$args|% t*y`
[Answer]
You can access static methods via instance:
```
$x=4,2,3
$x::Sort($x) # [Array]::Sort($x)
"$x" # 2 3 4
$x::Reverse($x) # [Array]::Reverse($x)
"$x" # 4 3 2
```
BigInteger suffix (`n`) introduced in PowerShell 7:
```
(0n)::Pow(4,5) # [bigint]::Pow(4,5)
(0n)::Abs(-3) # [bigint]::Abs(-3)
2*0n::Abs(-3) # some cases don't require parentheses
```
]