【问题标题】:How can I specify that the value of a variable in VBscript be case insensitive?如何指定 VBscript 中变量的值不区分大小写?
【发布时间】:2014-10-08 03:40:32
【问题描述】:

我在 HTA 中编写的 VBscript 的一部分要求用户在文本框中输入名称,该文本框将生成具有该名称的文件夹。我正在检查脚本以确保没有使用非法字符或名称。我陷入困境的地方是试图确保如果用户输入 COM1 或 LPT1,他们将被告知不允许他们尝试使用的名称,而不是出现脚本错误。问题是如果不为 COM1 到 COM9 和 LPT1 到 LPT9 中的字母可以在不同情况下排列(例如 com1、Com1、cOm1 等)的所有可能方式编写 If 语句,我无法弄清楚如何做到这一点。下面的代码 sn-p 说明了我的意思。

sFldrName = BasicTextbox.Value
sFldrBadMsg = "You've chosen an illegal folder name."

If sFldrname = "COM1" Then
  Msgbox  sFldrBadMsg
ElseIf sFldrname = "COM2" Then
  Msgbox  sFldrBadMsg
ElseIf sFldrname = "COM3" Then
  Msgbox  sFldrBadMsg

在上面的示例中,用户在文本框中输入的任何内容都分配给“sFldrname”。然后脚本检查分配给“sFldrname”的字符串是COM1 还是COM2 还是COM3。问题是我只能在指定的确切情况下检查这些字符串。如果用户输入 COM1,他们会收到我的警告信息。但是,如果他们输入 com1(全小写)或 CoM1(混合大小写),他们将收到脚本错误,因为无论大小写如何,它仍然是非法名称。为了用我上面使用的方法来解决这个问题,我必须做这样的事情:

sFldrName = BasicTextbox.Value
sFldrBadMsg = "You've chosen an illegal folder name."

If sFldrname = "COM1" Then
  Msgbox  sFldrBadMsg
ElseIf sFldrname = "Com1" Then
  Msgbox  sFldrBadMsg
ElseIf sFldrname = "COm1" Then
  Msgbox  sFldrBadMsg
ElseIf sFldrname = "cOm1" Then
  Msgbox  sFldrBadMsg
ElseIf sFldrname = "coM1" Then
  Msgbox  sFldrBadMsg
ElseIf sFldrname = "cOM1" Then
  Msgbox  sFldrBadMsg
ElseIf sFldrname = "CoM1" Then
  Msgbox  sFldrBadMsg
ElseIf sFldrname = "com1" Then
  Msgbox  sFldrBadMsg

对于 COM2 到 COM9 和 LPT1 到 LPT9,我也必须这样做。我真的不想这样做。那么,当我检查“sFldrname”的值以查看它是什么字符串时,有没有办法忽略该字符串的大小写?或者,有没有更好的方法来做我想做的事情?谢谢。

【问题讨论】:

    标签: vbscript


    【解决方案1】:

    正如其他人已经提到的,规范的方法是将要比较的变量的值大写(或小写):

    If LCase(sFldrname) = "com1" Then
      Msgbox  sFldrBadMsg
    ElseIf LCase(sFldrname) = "com2" Then
      Msgbox  sFldrBadMsg
    ElseIf LCase(sFldrname) = "com3" Then
      Msgbox  sFldrBadMsg
    End If
    

    使用StrComp 函数将是另一种选择:

    If StrComp(sFldrname, "COM1", vbTextCompare) = 0 Then
      Msgbox  sFldrBadMsg
    ElseIf StrComp(sFldrname, "COM2", vbTextCompare) = 0 Then
      Msgbox  sFldrBadMsg
    ElseIf StrComp(sFldrname, "COM3", vbTextCompare) = 0 Then
      Msgbox  sFldrBadMsg
    End If
    

    但是,由于您要对同一变量进行 n 向比较,因此您最好的选择可能是 Select 语句与 UCaseLCase 结合使用:

    Select Case UCase(sFldrname)
      Case "COM1", "COM2", "COM3" : MsgBox sFldrBadMsg
      Case Else : MsgBox "OK"
    End Select
    

    【讨论】:

    • 我喜欢 Select Case 方法。问题是如果输入了像 COM1 这样的非法名称,在我的警告消息出现并被确认后,脚本将继续运行并继续运行到稍后在代码中创建文件夹的位置。因此,在我单击消息框上的“确定”并显示有关非法文件夹名称的警告后,我会立即收到与非法文件夹名称相同的脚本错误。单击消息框中的“确定”后,我需要某种方法来停止脚本。有什么想法吗?
    • 糟了!我意识到我需要做的就是在“End Select”之前的一行中添加“Exit Sub”,它的工作方式与我询问的方式相同。感谢您的解决方案。
    • 我不反对这个答案 jkolb,但您需要考虑您在这里写的内容。如果你这样做,那么你必须能够从 COM1 匹配到 COM...任何东西。 LPT 也是如此。您将遭受我们所说的“代码膨胀”。请考虑我通过 RegEx 为您提供的解决方案,因为它可以一次性处理所有内容。一个测试,产生更快的代码,更可靠的代码......如果你想要一种调用函数的方法,或者执行某种测试,并且能够执行类似 Perl“或死”运算符的东西,我可以展示你在另一个答案/问题中。
    • 我在下面评论了您的解决方案。看看并给我一些反馈。
    • @LarryF 这是rather finite list,所以这不是真正的问题。
    【解决方案2】:

    好吧,你可以这样做:

    If UCase(sFldrname) = "COM1" Then
      Msgbox  sFldrBadMsg
    end if
    

    这将使您的字符串大写,然后您可以将结果与所有大写进行比较。您最好只查找 COM 和冒号。现在,为了最好的安全性,。并确保路径是正确的,你想研究一些更严肃的东西,比如正则表达式。正则表达式可以获取用户输入并测试它是否为有效的“类似路径”字符串。

    类似:

    Dim RegEx, bFound
    Set RegEx = New RegExp
    RegEx.IgnoreCase = True
    RegEx.Pattern = "^(?:\b((?#drive)[a-z]):\\((?#folder)[^/:*?""<>|\r\n]*\\)?((?#file)[^\\/:*?""<>|\r\n]*))$"
    bFound = RegEx.Test(Data)
    

    当用户输入有效的驱动器、文件夹和文件名时将匹配。或者,您使用 RegEx 的其他迭代来测试匹配。请记住,您不必检查“COM1:”、“LPT1:”等,因为正则表达式不允许路径中出现冒号,除非在驱动器号的开头...

    Dim RegEx
    Set RegEx = New RegExp
    RegEx.IgnoreCase = True
    RegEx.Pattern = "\b((?#drive)[a-z]):\\((?#folder)[^/:*?""<>|\r\n]*\\)?((?#file)[^\\/:*?""<>|\r\n]*)"
    If RegEx.Test(sFldrname ) Then
        ' Successful match
    Else
        ' Match attempt failed
    End If
    

    现在,假设您要测试用户输入中的 DOS 设备名称。您可以使用如下的 RegEx 来测试 COMn:、LPTn:、CON: 和 NIL: 的所有组合。当然,这个 RegEx 要求输入 START 带有 COM、LPT、CON 等,如果字符串不以它开头,比如说,他们输入了一个目录名称 Welcome,或者见鬼,当 WelCOM3: 正则表达式不匹配时,表示一条干净的路径。如果您希望它能够在整个输入字符串中搜索 COM{n}: 的外观,则将 \b 从模式中删除...

    Dim RegEx
    Set RegEx = New RegExp
    RegEx.IgnoreCase = True
    RegEx.Pattern = "\b(COM[0-9]+|LPT[0-9]+|CON|NIL)\:"
    If RegEx.Test(sFldrname ) Then
        ' We discovered a DOS Device name as a PATH, and it is therefore invalid.
    End If
    

    现在,为了解决您的实际问题,您会注意到RegEx.IGNORECASE = true。那是你的王牌……

    在我的第一个示例中,我只是向您展示了如何进行不区分大小写的字符串比较的课程,您将经常使用它来编写几乎任何语言的任何代码。我向您展示的其他示例更像是一种“正确”的方式,或者是一种“更简单”的方式,或者是一种更“可靠”的方式来搜索路径中的坏事。我认为重要的是你要研究一些更可靠的东西,并且你的代码要少得多,以获得更稳定的代码库。由于您正在处理 PATHS,如您所知,这是一种严重的能力,可以让某人输入可能将它们放在错误文件夹中的路径名,(例如,现在输入像 ..\..\..\..\..\..\Windows\System32\ 这样的文件夹名称,他们最终会一个在 Windows System32 中创建的文件夹,根据您的应用程序的功能,这可能是一个严重的安全风险。所以,不要只使用我演示的正则表达式。您可以使用诸如强制起始目录作为程序主目录之类的策略目录,并吃任何句点,反斜杠和任何其他“路径”字符,并强制在您的主目录下创建目录。希望这会有所帮助,抱歉数据泛滥,但我们都去过你的地方是!

    【讨论】:

    • 我实际上确实在我的代码的另一部分中使用了 RegEx,以确保不使用非法字符,例如 : 和 \。虽然我对 RegEx 不太熟悉,但我不知道如何使用它来确保输入不仅仅是单词 COM1。 COM1 可以作为名称的一部分,只要它不是没有其他内容的完整名称。
    • 我可以让 RegEx 识别我指定的任何模式是否存在于用户输入中,因此它有利于检查一组字符。但在 COM1、COM2 等的情况下,我不希望它只检查它的存在,因为如果它存在就可以了。我希望能够检查输入是否只是 COM1(不区分大小写),如果是则阻止它。因此,如果用户输入 COM1,它将被阻止,但如果用户输入 ABCOM1,它将被允许。我能够弄清楚如何使用 RegEx 这两个输入的唯一方法将被阻止。有什么想法吗?
    • 当然。创建一个 RegEx 模式,可能是这样的:"\b(COM[0-9]+|LPT[0-9]+|CON|NIL)\:" (不带引号,或者实际上,分配它们对于模式,你需要引号,但是。你知道......)。这将检查 COMx: 其中 x 将在 0 到 ~40 亿之间,与 LPT 相同,我将 CON: 和 NIL: 扔在那里,因为它们也是 DOS 设备名称,可能会对您的路径造成严重破坏。在我最初的答案中,我有点明白,你应该将他们想要创建的路径附加到你要创建它的位置,然后测试整个事情以确保它是一个有效的路径
    • 我提供的正则表达式。无论如何,看看当前的正则表达式,你会看到 \b?这告诉 RegEx 匹配器这必须在字符串的开头匹配。因此,如果他们创建一个像 welCOMe 这样的文件夹,模式将不匹配,告诉您提供的路径是好的。另外,我在最后包括了 \:?这告诉匹配器匹配 COM1:,而不仅仅是 COM1。 COM1 是有效路径,但 COM1: 不是。在某个地方,我使用 RegEx 在 DLL 中处理了这个确切的问题。如果我挖掘代码,我会在这里为您发布。希望这对人有所帮助......
    • 谢谢,它确实有帮助。我在脚本中使用的另一个 RegEx 已经检查了是否存在 : 和其他非法字符,因此 COM1: 之类的内容已经不允许这样做。您当前的 RegEx 检查输入是否以 COM1 开头,但如果文件夹名称以 COM1 开头,只要文件夹名称中有其他内容,这样建议的文件夹名称不只是 COM1,就可以。有没有办法使用 RegEx 来检查输入是否只包含 COM1 之类的字符串?
    【解决方案3】:

    将输入转换为大写,然后与您的大写禁止字符串进行比较:

    If uCase(sFldrname) = "COM1" Then
    ...
    

    为避免禁用字符串出错,请将它们也大写:

    If uCase(sFldrname) = uCase("COM1") Then
    ...
    

    【讨论】:

      猜你喜欢
      • 2023-03-20
      • 2015-06-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-27
      • 1970-01-01
      • 2013-03-06
      • 1970-01-01
      相关资源
      最近更新 更多