You guys are making this too hard. PowerShell handles this quite elegantly e.g.:
> $str1 = $null
> if ($str1) { 'not empty' } else { 'empty' }
empty
> $str2 = ''
> if ($str2) { 'not empty' } else { 'empty' }
empty
> $str3 = ' '
> if ($str3) { 'not empty' } else { 'empty' }
not empty
> $str4 = 'asdf'
> if ($str4) { 'not empty' } else { 'empty' }
not empty
> if ($str1 -and $str2) { 'neither empty' } else { 'one or both empty' }
one or both empty
> if ($str3 -and $str4) { 'neither empty' } else { 'one or both empty' }
neither empty
Answer from Keith Hill on Stack OverflowYou guys are making this too hard. PowerShell handles this quite elegantly e.g.:
> $str1 = $null
> if ($str1) { 'not empty' } else { 'empty' }
empty
> $str2 = ''
> if ($str2) { 'not empty' } else { 'empty' }
empty
> $str3 = ' '
> if ($str3) { 'not empty' } else { 'empty' }
not empty
> $str4 = 'asdf'
> if ($str4) { 'not empty' } else { 'empty' }
not empty
> if ($str1 -and $str2) { 'neither empty' } else { 'one or both empty' }
one or both empty
> if ($str3 -and $str4) { 'neither empty' } else { 'one or both empty' }
neither empty
You can use the IsNullOrEmpty static method:
[string]::IsNullOrEmpty(...)
how to check a value is that null in powershell script
powershell - Check if a string is not NULL or EMPTY - Stack Overflow
PowerShell $null Variable in an IF Statement
Null coalescing in PowerShell - Stack Overflow
Videos
If(!$Variable) vs if($Variable -eq $null)
Is there much difference or clear advantages between the two?
if (-not ([string]::IsNullOrEmpty($version)))
{
$request += "/" + $version
}
You can also use ! as an alternative to -not.
You don't necessarily have to use the [string]:: prefix. This works in the same way:
if ($version)
{
$request += "/" + $version
}
A variable that is null or empty string evaluates to false.
The problem is here:
$UserPref = if ($UserPref -eq $null){$UserPrefN = $UserGN} Else{$UserPrefN = $UserPref}
You’re doing a comparison on the $UserPref variable which has not been set because the comparison is in the assignment statement. This is not technically illegal, but you have strict mode on which will throw an error when you reference a variable that hasn’t been initiated. You can avoid this error by skipping the Set-StrictMode cmdlet.
However, the way you are assigning the $UserPref variable seems a bit wonky to me. It looks like you’re trying to check if it’s already set and then set some other variable values based on this comparison. Since each action you’re taking in the if construct is an assignment, there is no need to encapsulate those in the $UserPref assignment. Also, instead of checking for -eq $null in the if condition, you could just check for the existence of $UserPref:
if (!$UserPref){$UserPref = $UserGN}
I know I’m going to be kicking myself, but since I still consider myself a n00b with PS, I’ll try not to kick too hard.
I’ve got a script for new hires that works intermittently. HR insists that AD accounts use a person’s legal name, however many people prefer their nicknames for their email and display names, so a PreferredName field was created in HRIS. I’m checking for a preferred name ($UserPref) and if it exists I assign it to $UserPrefN and if it doesn’t, I assign their first name ($UserGN) to $UserPrefN. If $UserPref is blank ($null), sometimes it works and sometimes it doesn’t, lately more often than not it doesn’t and $UserPrefN doesn’t get set. It’s got to be my syntax, but I don’t see it.
[PS] C:\Windows\system32>Set-Strictmode -Version Latest -Verbose
[PS] C:\Windows\system32>$User = 'AccountName'
[PS] C:\Windows\system32>$UserSN = 'LastName'
[PS] C:\Windows\system32>$UserGN = 'FirstName'
[PS] C:\Windows\system32>$UserFI = $UserGN.substring(0,1)
[PS] C:\Windows\system32>$UserPref =
>> if ($UserPref -eq $null){$UserPrefN = $UserGN} Else{$UserPrefN = $UserPref}
>>
The variable '$UserPref' cannot be retrieved because it has not been set.
At line:2 char:5
+ if ($UserPref -eq $null){$UserPrefN = $UserGN} Else{$UserPrefN = $UserPref}
+ ~~~~~~~~~
+ CategoryInfo : InvalidOperation: (UserPref:String) [], RuntimeException
+ FullyQualifiedErrorId : VariableIsUndefined
[PS] C:\Windows\system32>
[PS] C:\Windows\system32>echo $UserPrefN
The variable '$UserPrefN' cannot be retrieved because it has not been set.
At line:1 char:6
+ echo $UserPrefN
+ ~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (UserPrefN:String) [], RuntimeException
+ FullyQualifiedErrorId : VariableIsUndefined
PowerShell 7+
PowerShell 7 introduces native null coalescing, null conditional assignment, and ternary operators in PowerShell.
Null Coalescing
$null ?? 100 # Result is 100
"Evaluated" ?? (Expensive-Operation "Not Evaluated") # Right side here is not evaluated
Null Conditional Assignment
null
$x ??= 100 # $x is now 100
$x ??= 200 # $x remains 100
Ternary Operator
$true ? "this value returned" : "this expression not evaluated"
$false ? "this expression not evaluated" : "this value returned"
Previous Versions
There isn’t any need for the PowerShell Community Extensions, you can use the standard PowerShell if statements as an expression:
variable = if (condition) { expr1 } else { expr2 }
So to the replacements for your first C# expression of:
var s = myval ?? "new value";
becomes one of the following (depending on preference):
myval -eq $null) { "new value" } else { $myval }
myval -ne $null) { $myval } else { "new value" }
or depending on what $myval might contain you could use:
myval) { $myval } else { "new value" }
and the second C# expression maps in a similar way:
var x = myval == null ? "" : otherval;
becomes
myval -eq $null) { "" } else { $otherval }
Now to be fair, these aren't very snappy, and nowhere near as comfortable to use as the C# forms.
You might also consider wrapping it in a very simple function to make things more readable:
function Coalesce(
b) { if (
null) { $a } else { $b } }
$s = Coalesce $myval "new value"
or possibly as, IfNull:
function IfNull(
b, $c) { if ($a -eq $null) { $b } else { $c } }
$s = IfNull $myval "new value" $myval
$x = IfNull $myval "" $otherval
As you can see a very simple function can give you quite a bit of freedom of syntax.
One extra option to consider in the mix is a more generic IsTrue function:
function IfTrue(
b, $c) { if ($a) { $b } else { $c } }
$x = IfTrue ($myval -eq $null) "" $otherval
Then combine that is PowerShell's ability to declare aliases that look a bit like operators, you end up with:
New-Alias "??" Coalesce
myval "new value"
New-Alias "?:" IfTrue
q -eq "meaning of life") 42 $otherval
Clearly this isn't going to be to everyone's taste, but may be what you're looking for.
As Thomas notes, one other subtle difference between the C# version and the above is that C# performs short-circuiting of the arguments, but the PowerShell versions involving functions/aliases will always evaluate all arguments. If this is a problem, use the if expression form.
PowerShell 7 and later
PowerShell 7 introduces many new features and migrates from .NET Framework to .NET Core. As of mid-2020, it hasn't completely replaced legacy versions of PowerShell due to the reliance on .NET Core, but Microsoft has indicated that they intend for the Core family to eventually replace the legacy Framework family. By the time you read this, a compatible version of PowerShell may come pre-installed on your system; if not, see https://github.com/powershell/powershell.
Per the documentation, the following operators are supported out-of-the-box in PowerShell 7.0:
Null-coalescing:
??Null-coalescing assignment:
??=Ternary:
... ? ... : ...
These work as you would expect for null coalescing:
a ??
c ?? 'default value'
$y ??= 'default value'
Since a ternary operator has been introduced, the following is now possible, though it's unnecessary given the addition of a null coalescing operator:
a -eq $null ?
a
As of 7.0, the following are also available if the PSNullConditionalOperators optional feature is enabled, as explained in the documentation (1 and 2):
Null-conditional member access for members:
?.Null-conditional member access for arrays et al:
?[]
These have a few caveats:
Since these are experimental, they're subject to change. They may no longer be considered experimental by the time you read this, and the list of caveats may have changed.
Variables must be enclosed in
${}if followed by one of the experimental operators because question marks are permitted in variable names. It's unclear if this will be the case if/when the features graduate from experimental status (see issue #11379). For example,${x}?.Test()uses the new operator, but$x?.Test()runsTest()on a variable named$x?.There is no
?(operator as you might expect if you're coming from TypeScript. The following won't work:$x.Test?()
PowerShell 6 and earlier
PowerShell versions prior to 7 do have an actual null coalescing operator, or at least an operator that is capable of such behavior. That operator is -ne:
# Format:
# (
b,
null)[0]
($null, 'alpha', 1 -ne $null)[0]
# Output:
alpha
It's a bit more versatile than a null coalescing operator, since it makes an array of all nonnull items:
$items = $null, 'alpha', 5, 0, '', @(), $null, $true, $false
$instances = $items -ne $null
[string]::Join(', ', ($instances | ForEach-Object -Process { $_.GetType() }))
# Result:
System.String, System.Int32, System.Int32, System.String, System.Object[],
System.Boolean, System.Boolean
-eq works similarly, which is useful for counting null entries:
($null, 'a', $null -eq $null).Length
# Result:
2
But anyway, here's a typical case to mirror C#'s ?? operator:
'Filename: {0}' -f ($filename, 'Unknown' -ne $null)[0] | Write-Output
Explanation
This explanation is based on an edit suggestion from an anonymous user. Thanks, whoever you are!
Based on the order of operations, this works in following order:
The
,operator creates an array of values to be tested.The
-neoperator filters out any items from the array that match the specified value--in this case, null. The result is an array of non-null values in the same order as the array created in Step 1.[0]is used to select the first element of the filtered array.
Simplifying that:
Create an array of possible values, in preferred order
Exclude all null values from the array
Take the first item from the resulting array
Caveats
Unlike C#'s null coalescing operator, every possible expression will be evaluated, since the first step is to create an array.
If you compare to $null is PowerShell, you turn it around.
But you may as well just test for the variable, as if it’s null if will treat it like false.
if($null -eq $something){
#Do Stuff
}
# test variable:
if($something){
#Do Stuff
}
rencore.com
PowerShell – Null comparison demystified
I have been working recently on the guidance for PowerShell rules. Rule research requires a lot of research and digging into how a programming language […]
THere is also ‘get-variable’
So I have a series of inputs that are captured in Variables. Let’s say $Var1 through $Var9
What I need is to have all variables with “something” in them. These are strings.
I can test each $Var and see if it has something in it, but I’m trying to see is any of them is empty. I would prefer not to do about 10 if statements, but I can’t think of another way.
For example, I can do:
If($Var1-like $Null){
Write-Output "Error no data"
}
Or
If($var2.length -gt 0){
Write-Output "There's something here..."
}
But I would rather not make 10 test conditions. Is there an “If any of these is empty” test? Or do I need to test each variable in a separate test condition?
(I know I can do it where an IF statement has multiple conditions, but… I’d prefer one test for all variables rather than 9 tests whether they are in 9 IF statements or 9 conditions in one IF)