使用正则表达式从文件中提取行和基于字段的行部分

时间:2017-07-20 16:33:36

标签: regex powershell text-parsing

-CASServer V2.00 connection from 127.0.0.1 [] Diag mode only
Clients: Static 0/50  Dynamic 17/50
Sampler: 1 0x1074bd8 hSock(0x2d0)
Archiver: 0 0
OK    
0x1078b08:0x2fc  192.168.2.182  WorkStation84021  Dynamic  07:55:25 07/20/17    
0x1076d78:0x370  192.168.6.158  WorkStation84144  Dynamic  08:19:29 07/20/17    
0x1076f28:0x38c  192.168.3.75  WorkStation21590  Dynamic  08:27:56 07/20/17    
0x1089a98:0x394  192.168.12.147  WorkStation93778  Dynamic  08:29:50 07/20/17    
0x1089d68:0x378  192.168.2.200  WorkStation53283  Dynamic  08:34:03 07/20/17    
0x108a038:0x2d8  192.168.4.145  WorkStation38642  Dynamic  08:35:19 07/20/17    
0x108a308:0x35c  192.168.5.103  WorkStation35979  Dynamic  08:44:24 07/20/17    
0x108be80:0x37c  192.168.6.155  WorkStation53023  Dynamic  08:49:48 07/20/17    
0x107b7f8:0x360  192.168.5.104  WorkStation53269  Dynamic  08:50:45 07/20/17    
0x107bac8:0x384  192.168.2.244  WorkStation53297  Dynamic  08:51:53 07/20/17    
0x107bd98:0x36c  192.168.4.157  WorkStation53239  Dynamic  08:54:01 07/20/17    
0x107c230:0x3a4  192.168.5.7  WorkStation53229  Dynamic  08:59:29 07/20/17    
0x107c7e0:0x3ac  192.168.12.146  WorkStation93784  Dynamic  08:59:31 07/20/17    
0x107ce60:0x3b0  192.168.4.173  WorkStation53179  Dynamic  09:01:12 07/20/17    
0x107c710:0x3b4  192.168.2.175  WorkStation53047  Dynamic  09:02:06 07/20/17    
0x107cf30:0x368  192.168.5.85  SERVER53116  Dynamic  09:05:14 07/20/17    
0x107c3d0:0x3a8  192.168.5.126  WorkStation53279  Dynamic  09:06:36 07/20/17    
OK    
Unknown DIAG command    
OK

我需要帮助解析这个文本文件。我想得到第二行"动态#/ 50"并想提取它。

我还想知道是否有以SERVER开头的工作站名称 如果找到一个,那么我想提取IP,工作站名称和时间/日期。

我不确定解决这个问题的最佳方法是什么。 我知道我的文件不会变得非常大(最多行数约为70行)。出于某种原因,我的Telnet输出是在每个语句之间添加空行

2 个答案:

答案 0 :(得分:1)

提取完整行的最方便(尽管很慢)方法是使用 Select-String

> (Get-Content file | Select-String -List '\bDynamic \d+/50\b').Line
Clients: Static 0/50  Dynamic 17/50

虽然 Select-String接受多个正则表达式,但您甚至只能从.Matches的{​​{1}}属性中提取匹配的部分/捕获组[Microsoft.PowerShell.Commands.MatchInfo]属性输出的实例,您的复杂提取需求使Select-String不切实际。

因此,自定义逻辑是必需的:

注意:以下解决方案将输入文件整体读入内存 可行输入文件< / strong>和你一样; 对于较大的文件(或用于处理命令输出),请使用基于管道的解决方案Select-String ,这将更慢,但记忆效率 - 见底:

ForEach-Object

以上产量:

# Read the entire file into an array of strings (line by line).
$lines = Get-Content file

# Extract the "Dynamic #/50" line
$lines -match '\bDynamic \d+/50\b'  # an array-valued LHS makes -match act as a filter

# Extract the server information.
foreach ($line in $lines) {
  $fields = -split $line  # split the line Awk-style into whitespace-separated fiels
  if ($fields[2] -match '^Server') { # check if 2nd fields starts with 'Server'
    $fields[1, 2, 4, 5] -join ' ' # join the fields of interest with a space and output
  }
}

等效的基于管道的解决方案

同样,这将更节省内存,但更慢 除了性能问题之外,基于管道的解决方案通常更简洁,概念更优雅

Clients: Static 0/50  Dynamic 17/50
192.168.5.85 SERVER53116 09:05:14 07/20/17

答案 1 :(得分:0)

您没有向社区提供其他人可以学习的脚本,因此我不愿意为您发布完整的答案。我会给你一个顶级评估,如果你发布你的剧本但仍然有问题,那么我会进一步帮助你。

您的文件有3种分区内容格式。每个都需要不同的解析方法。我们可以将它们称为顶部,中间和底部,我们可以通过“确定”将它们分开。文本。我们也可以忽略底部内容区域,因为它不包含任何符合您要求的有用数据。

首先获取文件的内容: $rawContent = get-content "c:\temp\yourfile.txt"

现在通过&#39; Ok&#39;打破内容。串: $contentAreas = ($rawContent -split "Ok")

现在每个内容区域可以单独使用。 $contentAreas[0]将输出顶级数据集 $contentAreas[1]将输出中间数据集

我建议您首先使用中间区域,因为它稍微容易一些。在这里,您可以使用where子句来查找匹配&#34; SERVER &#34;的行。然后,您可以为该行解析所需的值。

接下来,您可以使用顶部区域。在这里,我建议您使用.Split()通过空格(空格,制表符和新行)拆分内容。然后你可以使用.IndexOf按名称查找字段并从那里开始工作。

同样,如果你发布了一些显示努力并给我一些工作的东西,我将很乐意为你提供进一步的帮助。