Converting VBScript's Eqv Operator

2019-07-15 04:02发布

问题:

If you google for PowerShell Eqv you currently will find the VBScript-to-Windows PowerShell Conversion Guide on top of the list. Yet the answer is much of technical help:

Eqv Operator

Definition: Performs a logical equivalence on two expressions.
No doubt Eqv has its uses; we’re just not sure if it has any practical uses. Although there might be a Windows PowerShell equivalent we have to be honest: we didn’t look real hard for one.

In fact, I used the Eqv operator (also written as: A↔B) a number of times in VBScript and likely would have used it in PowerShell if it existed.

Example

I have a list of groups ("HR", "SAP", "!IT", "..."). If a user is a member of all the listed groups and explicitly not a member of groups that are preceded with an escalation mark (like "!IT", which is unraveled to: $Negate = $True and $Group = "IT") a specific task should be done. The script needs to iterate through the groups and immediately break the iteration when a group condition is not met (to save time).
A command for this would have been something like:

If ($Negate -eqv (IsMember($Group))) {Break}

How can I build a logical equivalence operator with a minimum of code?

回答1:

If you take definition quiet literally, you will probably already see a possible way to achieve a logical equivalence operation:

If ([Bool]$Expression1 -eq [Bool]$Expression2) {...}

But if you take a close look to the truth table you might notice that the results for Eqv are exactly the opposite of an Xor operation. Meaning that you can also achieve logical equivalence operation with an inverted Xor:

If (!(Expression1 -xor $Expression2)) {...}

And as it doesn’t matter what you invert for an Xor (either the whole operation or one of the expressions), you can even simplify it to:


If (!Expression1 -xor $Expression2) {...}

Check

0..3 | ForEach {
    $Expression1, $Expression2 = [Int]($_ / 2), [Int]($_ % 2)
    New-Object PSObject -Property @{
        Expression1 = [Bool]$Expression1
        Expression2 = [Bool]$Expression2
        Equivalence = !$Expression1 -xor $Expression2
    }
} | Format-Table -AutoSize

Truth Table

Expression1 Expression2 Equivalence
----------- ----------- -----------
      False       False        True
      False        True       False
       True       False       False
       True        True        True

Note: In this solution $Null expressions are considered $False. This differs from the VBScript Eqv implementation but is consistent with other PowerShell operators that contain $Null expressions. e.g. The VBScript statement: If 1 And vbNull Then msgbox "True" Else msgbox "False", returns True where the PowerShell statement If (1 -and $Null) {"True"} Else {"False"}, returns False.

Bitwise

If you looking for a bitwise Eqv operator (which should probably be called -bEqv, if it existed), then it would be:

$Equivalence = -bNot Expression1 -bXOr Expression2    # e.g.: -bNot 3 -bXOr 5 = -7 (-bAnd 0xF = 9)