代码之家  ›  专栏  ›  技术社区  ›  Valrok

解析文本文件并写出数据

  •  0
  • Valrok  · 技术社区  · 13 年前

    我正在执行创建powershell脚本的第一步,该脚本将读取打印机日志(可能使用get-WMI cmdlet),并解析日志。之后,我计划将脚本输出到一个.txt文件中——打印机的名称、打印机使用次数的计数器(如果可能的话)以及日志中的特定信息。

    为了做到这一点,我决定试着逆向工作。以下是日志的一小部分内容:

    10         Document 81, A361058/GPR0000151814_1: owned by A361058 was printed on R3556 via port IP_***.***.***.***.  Size in bytes: 53704; pages printed: 2                                                                  20130219123105.000000-300  
    10         Document 80, A361058/GPR0000151802_1: owned by A361058 was printed on R3556 via port IP_***.***.***.***.  Size in bytes: 53700; pages printed: 2   
    

    向后工作,只专注于首先解析,我希望能够特别地获得“/GRP”,“R3446(通常,R* * 因为这是打印机名称),并获取一个计数器,显示特定打印机在日志文件中出现的频率。

    我上一次使用Powershell已经有一段时间了,但目前这是我为了实现我的目标而设法创建的:

    Select-String -Path "C:\Documents and Settings\a411882\My Documents\Scripts\Print Parse Test.txt" -Pattern "/GPR", " R****" -AllMatches -SimpleMatch 
    

    该代码不会产生任何错误,但我也无法在屏幕上显示任何输出,以查看我是否正在捕获/GRP和打印机名称。目前,我正在努力确保在担心任何计数器之前收集到正确的输出。有人能帮助我,告诉我我的代码哪里出了问题吗?

    谢谢

    编辑:修复了我的代码中的一个小错误,该错误导致屏幕上没有显示任何数据。目前,此代码输出整个两行测试文本,而不是仅输出/GPR和服务器名称。新输出如下:

    My Documents\Scripts\Print Parse Test.txt:1:10         Document 81, A361058/GPR0000151814_1: owned by A361058 was printed on
     R3556 via port IP_***.***.***.***.  Size in bytes: 53704; pages printed: 2                                                  
                    20130219123105.000000-300  
    My Documents\Scripts\Print Parse Test.txt:2:10         Document 80, A361058/GPR0000151802_1: owned by A361058 was printed on
     R3556 via port IP_***.***.***.***.  Size in bytes: 53700; pages printed: 2  
    

    我想试着让它最终看起来像下面这样:

    /GPR, R****, count: ## (although for now I'm less concerned about the counter)
    
    2 回复  |  直到 13 年前
        1
  •  1
  •   Frode F.    13 年前

    你可以试试这个。它只在以下情况下返回一行 /GPR (以及“on”从“printed on”变为“on”)。

    Get-Content .\test.txt | % { 
        if ($_ -match '(?:.*)(/GPR)(?:.*)(?<=on\s)(\w+)(?:.*)') {
            $_ -replace '(?:.*)(/GPR)(?:.*)(?<=on\s)(\w+)(?:.*)', '$1,$2'
        }
    }
    

    输出:

    /GPR,R3556
    /GPR,R3556
    

    我相信有更好的正则表达式版本。我还在学习:-)

    编辑 这更容易阅读。正则表达式仍在那里进行提取,但我首先使用/GPR过滤掉行 select-string 相反:

    Get-Content .\test.txt | Select-String -SimpleMatch -AllMatches -Pattern "/GPR" | % {
        $_.Line -replace '(?:.*)(/GPR)(?:.*)(?<=on\s)(\w+)(?:.*)', '$1,$2'
    }
    
        2
  •  0
  •   mjolinor    13 年前

    我通常从我匹配的行的一个例子开始,并从中构建一个正则表达式,用正则表达式元字符代替文本的可变部分。这使得正则表达式更长,但以后阅读起来更直观。

    将正则表达式分配给一个变量,然后在后续代码中使用该变量,以防止正则表达式的混乱细节扰乱代码的其余部分:

    [regex]$DocPrinted = 
    'Document \d\d, \w+/(\D{3})[0-9_]+: owned by \w+ was printed on (\w+) via port IP_[0-9.]+  Size in bytes: \d+; pages printed: \d+'
    
    get-content <log file> |
    
    foreach {
     if ($_ -match $DocPrinted)
       {
         $line -match $docprinted  > $null 
         $matches 
       }
     }                                                           
    
    推荐文章