【问题标题】:Return line number or subsequent text of a text file string search返回文本文件字符串搜索的行号或后续文本
【发布时间】:2013-05-28 01:56:09
【问题描述】:

我有几个文本文件,每个文件都有数千行,这是典型行的示例:

PCI\VEN_10EC&DEV_8168&REV_09    Realtek\5x64\FORCED\PCIe_5.810.1218.2012\   Netrtle.inf Realtek 1   12/18/2012,5.810.1218.2012  Realtek PCIe GBE Family Controller

我正在编写的脚本对第一段文本进行字符串搜索:

PCI\VEN_10EC&DEV_8168&REV_09

我的脚本缩小了哪些文件有这个字符串,但我真正需要的是它在同一行返回下一个字符串:

Realtek\5x64\FORCED\PCIe_5.810.1218.2012\

一旦我有了这个字符串,我就可以继续执行脚本的其余部分,该脚本只是从 7zip 中提取 Realtek 文件夹。

我已经看到 Stack 上的其他语言已经完成了这项工作,但我找不到任何适用于 VBS 的内容。如果我知道如何更好地表达任务,我可能会找到答案。我真的很感激一些关于抓住第二个字符串的建议。

作为背景,这是我正在编写的脚本。它在 C:\scripts\ 中的所有文本文件中查找由 WMI 查询返回的字符串,以查找代码为 28(未安装驱动程序)的设备驱动程序的 CompatibleID:

Set objFSO = CreateObject("Scripting.FileSystemObject") 
Set objShell = CreateObject("Wscript.Shell") 
Set objNet = CreateObject("WScript.Network") 
Set objWMIService = GetObject("winmgmts:\\" & "." & "\root\CIMV2")
Set colItems = objWMIService.ExecQuery _ 
    ("Select * from Win32_PnPEntity " _ 
        & "WHERE ConfigManagerErrorCode = 28") 
For Each objItem in colItems 
 Dim arrCompatibleIDs
 aarCompatibleIDs = objItem.CompatibleID
 for each objComp in aarCompatibleIDs
 Dim FirstID
 FirstID = objComp
Exit For
Next 
Next

strSearchFor = firstID
objStartFolder = "C:\scripts"

Set objFolder = objFSO.GetFolder(objStartFolder)

Set colFiles = objFolder.Files
For Each objFile in colFiles
    'Wscript.Echo objFile.Name
    strFile = "C:\scripts\" & objFile.Name
    set objFile = objFSO.getFile(strFile)
    if objFile.size > 0 then
        If InStr(objFSO.OpenTextFile(strFile).ReadAll, strSearchFor) > 0 Then
            msgbox(objfile.name)
        Else
            WScript.Sleep (100)
        End If
    End If
Next

【问题讨论】:

    标签: vbscript


    【解决方案1】:

    如果你需要大海捞针寻找固定针和可变线程,你可以使用一些 InStr()s 或 RegExp。为了让您开始:

      Dim sHaystack : sHaystack = Join(Array( _
           "hay hay" _
         , "fixed_needle variable_thread hay" _
         , "hay hay" _
      ), vbCrLf)
      Dim sNeedle : sNeedle = "fixed_needle" & " "
      Dim nPosN   : nPosN   = Instr(sHaystack, sNeedle)
      If 0 < nPosN Then
         nPosN = nPosN + Len(sNeedle)
         Dim nPosT : nPosT = Instr(nPosN, sHaystack, " ")
         If 0 < nPosN Then
            WScript.Echo "Instr()", qq(Mid(sHaystack, nPosN, nPosT - nPosN))
         Else
            WScript.Echo "no thread"
         End If
      Else
         WScript.Echo "no needle"
      End If
      Dim reNT : Set reNT = New RegExp
      reNT.Pattern = sNeedle & "(\S+) "
      Dim oMTS : Set oMTS = reNT.Execute(sHayStack)
      If 1 = oMTS.Count Then
         WScript.Echo "RegExp ", qq(oMTS(0).SubMatches(0))
      Else
         WScript.Echo "no match"
      End If
    

    输出:

    Instr() "variable_thread"
    RegExp  "variable_thread"
    

    如果你把干草堆改成

      Dim sHaystack : sHaystack = Join(Array( _
           "hay hay" _
         , "fixed_needle no_variable_thread_hay" _
         , "hay hay" _
      ), vbCrLf)
    

    输出:

    Instr() "no_variable_thread_hay
    hay"
    no match
    

    您发现要使 Instr() 方法防弹,还需要做更多的工作。

    【讨论】:

      【解决方案2】:

      由于您的输入文件似乎是制表符分隔的,您可以这样做:

      Set wmi = GetObject("winmgmts://./root/cimv2")
      qry = "SELECT * FROM Win32_PnPEntity WHERE ConfigManagerErrorCode = 28"
      For Each entity In wmi.ExecQuery(qry)
        For Each cid In entity.CompatibleID
          firstID = cid
          Exit For
        Next
      Next
      
      Set fso = CreateObject("Scripting.FileSystemObject")
      For Each f In objFSO.GetFolder(objStartFolder).Files
        If f.Size > 0 Then
          For line In Split(f.OpenAsTextStream.ReadAll, vbNewLine)
            arr = Split(line, vbTab)
            If arr(0) = firstID Then MsgBox arr(1)
          Next
        End If
      Next
      

      一般来说,你不应该做这样的事情:

      Set colFiles = objFolder.Files
      For Each objFile in colFiles
        strFile = "C:\scripts\" & objFile.Name
        set objFile = objFSO.getFile(strFile)
        if objFile.size > 0 then
          If InStr(objFSO.OpenTextFile(strFile).ReadAll, strSearchFor) > 0 Then
      ...
      

      Files 集合已经包含 File 对象,因此从对象的属性构建路径名(顺便说一句,其中包含为您提供完整路径的 Path 属性)只是为了获得完全相同的对象是完全没有意义的你已经有了。另外,文件对象有一个方法OpenAsTextStream,所以你可以直接将它们作为文本文件打开,而不需要像objFSO.OpenTextFile(f.Path)那样走弯路。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-11-28
        • 2012-09-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-10-24
        • 1970-01-01
        相关资源
        最近更新 更多