vbscript字符串当一边为null时不等于其他

时间:2013-05-07 21:16:53

标签: string vbscript comparison

首先发布在这里。如果我应该在其他地方或其他地方发布,请随时告诉我。 :)

我用Google搜索了“字符串比较”和“字符串不等式”的变体,但它们的结果毫无用处。我的问题是我正在检查字符串不等式,当一方为空而另一方不是时,我得到了令人惊讶的结果。请考虑以下演示代码:

TestStr "foo", "foo", "="
TestStr "foo", "bar", "<>"
TestStr Null, "foo", "<>"
TestStr "foo", Null, "<>"

Sub TestStr(left, right, expected)
    ' I actually don't care about this - it's here for reference
    If left = right Then
        WScript.Echo "left = right - expected " & expected
    Else
        WScript.Echo "left <> right - expected " & expected
    End If

    If left <> right Then
        WScript.Echo "left <> right - expected " & expected
    Else
        WScript.Echo "left = right - expected " & expected
    End If
    WScript.Echo ""
End Sub

运行此代码会产生以下输出(“编码”,因此未格式化):

left = right - expected =
left = right - expected =

left <> right - expected <>
left <> right - expected <>

left <> right - expected <>
left = right - expected <>

left <> right - expected <>
left = right - expected <>

正如您所看到的,当一方为空而另一方不是时,字符串不等式会失败 - 我目前正在经历这种情况。我知道我可以做下面的事情,但我想知道我是否错过了一个更简单的方法:

If (left = right) Then
Else
    ' Do inequality stuff here...
End If

[编辑]我收到了很好的反馈为什么这种情况正在发生。谢谢大家!但是,我也对如何避免这种情况感兴趣。

[编辑2]我希望的是一种简单的方法来了解字符串何时不同(感谢Ekkehard.Horner的建议)。

  • 如果两者都为空,那么可以说它们不一样,但它们对我来说足够了。
  • 如果一个是空的而另一个不是,那么它们就不同了 - 很明显。
  • 如果两者都不为空,那么如果完全相同,则它们是相同的 - 包括区分大小写。

因此,就我的目的而言,“预期”以及我的演示代码中实际发生的事情是足够的。

3 个答案:

答案 0 :(得分:1)

我认为你错过了VBScript中Comparison Operators的基础。 与Null相比,始终返回Null,而不是布尔值(True / False)。

<强>更新

字符串比较区分大小写,但在某些情况下,您的脚本会将StringNull进行比较,而您的第二个问题是如何简化此任务,对吧?在这种情况下,编写函数是个好主意。

Function CompStr(sVal1, sVal2)
    CompStr = False
    If VarType(sVal1) <> vbString Then Exit Function
    If VarType(sVal2) <> vbString Then Exit Function
    CompStr = sVal1 = sVal2
End Function

答案 1 :(得分:1)

说明Panayot的陈述(+1)并使其易于实验:

  ' vbEmpty         0  Uninitialized (default)
  ' vbNull          1  Contains no valid data
  ' vbInteger       2  Integer subtype
  ' vbLong          3  Long subtype
  ' vbSingle        4  Single subtype
  ' vbDouble        5  Double subtype
  ' vbCurrency      6  Currency subtype
  ' vbDate          7  Date subtype
  ' vbString        8  String subtype
  ' vbObject        9  Object
  ' vbError        10  Error subtype
  ' vbBoolean      11  Boolean subtype
  ' vbVariant      12  Variant (used only for arrays of variants)
  ' vbDataObject   13  Data access object
  ' vbDecimal      14  Decimal subtype
  ' vbByte         17  Byte subtype
  ' vbArray      8192  Array
  Dim aData : aData = Array(Empty, Null, CInt(0), CLng(0), "", "a", Nothing)
  Dim sXfx  : sXfx  = Space(25)
  Dim k     : k     = 0
  Dim i, j
  For i = 0 To UBound(aData)
      For j = 0 To UBound(aData)
          WScript.Echo               _
               Right(1000 + k, 3)     _
             , Right(sXfx & toTypeStr(aData(i)), 25)   _
             , Left(toTypeStr(aData(j))& sXfx, 25)   _
             , compareX(aData(i), aData(j))
          k = k + 1
      Next
  Next

Function toTypeStr(vX)
  Dim aTmp : aTmp = Array(VarType(vX), TypeName(vX), "")
  Select Case aTmp(0)
    Case vbEmpty  : aTmp(2) = "<Empty>"
    Case vbNull   : aTmp(2) = "<Null>"
    Case vbString : aTmp(2) = """" & vX & """"
    Case vbObject : aTmp(2) = "<Object>"
    Case Else     : aTmp(2) = CStr(vX)
  End Select
  toTypeStr = Join(aTmp, ":")
End Function

Function compareX(vLHS, vRHS)
  Dim vEQ
 On Error Resume Next
  vEQ = vLHS = vRHS
  If Err.Number Then compareX = Err.Description : Exit Function : End If
 On Error GoTo 0
  Select Case True
    Case VarType(vEQ) = vbNull
      compareX = toTypeStr(vEQ) & " - can't compare with Null"
    Case VarType(vEQ) <> vbBoolean
      compareX = toTypeStr(vEQ) & " surprise"
    Case vEQ
      compareX = "equal"
    Case Else
      compareX = "not equal"
  End Select
End Function

输出:

000           0:Empty:<Empty> 0:Empty:<Empty>           equal
001           0:Empty:<Empty> 1:Null:<Null>             1:Null:<Null> - can't compare with Null
002           0:Empty:<Empty> 2:Integer:0               equal
003           0:Empty:<Empty> 3:Long:0                  equal
004           0:Empty:<Empty> 8:String:""               equal
005           0:Empty:<Empty> 8:String:"a"              not equal
006           0:Empty:<Empty> 9:Nothing:<Object>        Object variable not set
007             1:Null:<Null> 0:Empty:<Empty>           1:Null:<Null> - can't compare with Null
008             1:Null:<Null> 1:Null:<Null>             1:Null:<Null> - can't compare with Null
009             1:Null:<Null> 2:Integer:0               1:Null:<Null> - can't compare with Null
010             1:Null:<Null> 3:Long:0                  1:Null:<Null> - can't compare with Null
011             1:Null:<Null> 8:String:""               1:Null:<Null> - can't compare with Null
012             1:Null:<Null> 8:String:"a"              1:Null:<Null> - can't compare with Null
013             1:Null:<Null> 9:Nothing:<Object>        Object variable not set
014               2:Integer:0 0:Empty:<Empty>           equal
015               2:Integer:0 1:Null:<Null>             1:Null:<Null> - can't compare with Null
016               2:Integer:0 2:Integer:0               equal
017               2:Integer:0 3:Long:0                  equal
018               2:Integer:0 8:String:""               not equal
019               2:Integer:0 8:String:"a"              not equal
020               2:Integer:0 9:Nothing:<Object>        Object variable not set
021                  3:Long:0 0:Empty:<Empty>           equal
022                  3:Long:0 1:Null:<Null>             1:Null:<Null> - can't compare with Null
023                  3:Long:0 2:Integer:0               equal
024                  3:Long:0 3:Long:0                  equal
025                  3:Long:0 8:String:""               not equal
026                  3:Long:0 8:String:"a"              not equal
027                  3:Long:0 9:Nothing:<Object>        Object variable not set
028               8:String:"" 0:Empty:<Empty>           equal
029               8:String:"" 1:Null:<Null>             1:Null:<Null> - can't compare with Null
030               8:String:"" 2:Integer:0               not equal
031               8:String:"" 3:Long:0                  not equal
032               8:String:"" 8:String:""               equal
033               8:String:"" 8:String:"a"              not equal
034               8:String:"" 9:Nothing:<Object>        Object variable not set
035              8:String:"a" 0:Empty:<Empty>           not equal
036              8:String:"a" 1:Null:<Null>             1:Null:<Null> - can't compare with Null
037              8:String:"a" 2:Integer:0               not equal
038              8:String:"a" 3:Long:0                  not equal
039              8:String:"a" 8:String:""               not equal
040              8:String:"a" 8:String:"a"              equal
041              8:String:"a" 9:Nothing:<Object>        Object variable not set
042        9:Nothing:<Object> 0:Empty:<Empty>           Object variable not set
043        9:Nothing:<Object> 1:Null:<Null>             Object variable not set
044        9:Nothing:<Object> 2:Integer:0               Object variable not set
045        9:Nothing:<Object> 3:Long:0                  Object variable not set
046        9:Nothing:<Object> 8:String:""               Object variable not set
047        9:Nothing:<Object> 8:String:"a"              Object variable not set
048        9:Nothing:<Object> 9:Nothing:<Object>        Object variable not set

从#001和#007-#013可以看出,应用于Null值的操作(此处为:=)的结果始终为Null。

<强>更新

对于特殊情况(仅Null或Strings,两个Null都被认为是相等的):

  Dim aData : aData = Array(Null, "", "a")
  Dim sXfx  : sXfx  = Space(25)
  Dim k     : k     = 0
  Dim i, j
  For i = 0 To UBound(aData)
      For j = 0 To UBound(aData)
          WScript.Echo               _
               Right(1000 + k, 3)     _
             , Right(sXfx & toTypeStr(aData(i)), 25)   _
             , Left(toTypeStr(aData(j))& sXfx, 25)   _
             , CStr(compareStrNull(aData(i), aData(j)))
          k = k + 1
      Next
  Next

Function compareStrNull(vLHS, vRHS)
  Dim ntLHS : ntLHS = VarType(vLHS)
  Dim ntRHS : ntRHS = VarType(vRHS)
  Select Case True
'   If both are null, then one could argue that they aren't the same, but they're same enough for me.
    Case ntLHS = ntRHS And ntLHS = vbNull
      compareStrNull = True
'   If one is null and the other is not, then they're different - pretty obviously.
    Case ntLHS = vbNull Or ntRHS = vbNull
      compareStrNull = False
'   If both are not null, then they are the same if they're the exactly the same - including case sensitivity.
    Case ntLHS = ntRHS And ntLHS = vbString
      compareStrNull = vLHS = vRHS
    Case Else
      Err.Raise 4711, "compareStrNull", "surprise"
  End Select
End Function

输出:

000             1:Null:<Null> 1:Null:<Null>             True
001             1:Null:<Null> 8:String:""               False
002             1:Null:<Null> 8:String:"a"              False
003               8:String:"" 1:Null:<Null>             False
004               8:String:"" 8:String:""               True
005               8:String:"" 8:String:"a"              False
006              8:String:"a" 1:Null:<Null>             False
007              8:String:"a" 8:String:""               False
008              8:String:"a" 8:String:"a"              True

更新II:

比较功能的简化/优化版本:

Function compareStrNull02(vLHS, vRHS)
  compareStrNull02 = vLHS = vRHS                      ' native compare
  If VarType(compareStrNull02) = vbNull Then          ' at least one param is Null
     compareStrNull02 = VarType(vLHS) = VarType(vRHS) ' are both Null?
  End If
End Function

处理数组或对象需要进一步的工作。

答案 2 :(得分:-1)

尝试将其添加为第一行:

如果是isnull(左)或isnull(右)然后退出sub