[玩转系统] 使用 PowerShell 和正则表达式将文本转换为对象
作者:精品下载站 日期:2024-12-14 07:41:16 浏览:14 分类:玩电脑
使用 PowerShell 和正则表达式将文本转换为对象
PS C:\> "UNC is \server01\public" -match ""\(?<servername>\w+)\(?<sharename>\w+)"
True
PS C:\> $matches
Name Value
---- -----
servername server01
sharename public
0 \server01\public
当您知道名称时,您可以从 $matches 中获取值。
PS C:\> $matches.servername
server01
PS C:\> $matches.sharename
public
使用 REGEX 对象也可以,甚至更好一些。
PS C:\> [regex]$rx=""\(?<servername>\w+)\(?<sharename>\w+)"
PS C:\> $rx.Matches("UNC is \server01\public")
Groups : {\server01\public, server01, public}
Success : True
Captures : {\server01\public}
Index : 7
Length : 17
Value : \server01\public
PS C:\> $rx.Matches("UNC is \server01\public").groups
Groups : {\server01\public, server01, public}
Success : True
Captures : {\server01\public}
Index : 7
Length : 17
Value : \server01\public
Success : True
Captures : {server01}
Index : 9
Length : 8
Value : server01
Success : True
Captures : {public}
Index : 18
Length : 6
Value : public
使用 REGEX 对象,您可以获得名称。
PS C:\> $rx.GetGroupNames()
0
servername
sharename
PS C:\> $rx.GetGroupNames() | where {$_ -notmatch "\d+"}
servername
sharename
因为名称包含索引号,所以我通常将其过滤掉。一旦我知道了名称,我就可以使用它们来提取相关的匹配项。
PS C:\> $rx.Matches("UNC is \server01\public") | foreach {$_.groups["servername"].value; $_.groups[
"sharename"].value}
server01
public
然后我意识到在 PowerShell 中将其带到下一步并不需要太多。我有一个名称和一个值,为什么不创建一个对象呢?动态创建哈希表并使用它来创建自定义对象并不太困难。最终我想出了 ConvertFrom-Text。
#requires -version 3.0
Function ConvertFrom-Text {
<#
.SYNOPSIS
Convert structured text to objects.
.DESCRIPTION
This command will take structured text such as from a log file and convert it
to objects that you can use in the PowerShell pipeline. You can specify the
path to a text file, or pipe content directly into this command. The piped
content could even be output from command-line tools. You have to specify a
regular expression pattern that uses named captures. See examples.
.PARAMETER Pattern
A regular expression pattern that uses named captures. This parameter has an
alias of Regex.
.PARAMETER Path
The filename and path to the text or log file.
.PARAMETER Inputobject
Any text that you want to pipe into this command. It can be a certain number
of lines from a large text or log file. Or the output of a command line tool.
.EXAMPLE
PS C:\> $b = "(?<Date>\d{2}-\d{2}-\d{4}\s\d{2}:\d{2}).*(?<Error>\d+),\s+(?<Step>.*):\s+(?<Action>\w+),\s+(?<Path>(\w+\)*\w+\.\w+)"
PS C:\> convertfrom-text -pattern $b -path C:\windows\DtcInstall.log
Date : 10-18-2013 10:49
Error : 0
Step : CMsdtcUpgradePlugin::PostApply
Action : Enter
Path : com\complus\dtc\dtc\msdtcstp\msdtcplugin.cpp
Date : 10-18-2013 10:49
Error : 0
Step : CMsdtcUpgradePlugin::PostApply
Action : Exit
Path : com\complus\dtc\dtc\msdtcstp\msdtcplugin.cpp
...
The first command creates a variable to hold the regular expression pattern
that defines named captures for content in the DtcInstall.log. The second line
runs the command using the pattern and the log file.
.EXAMPLE
PS C:\> $wu = "(?<Date>\d{4}-\d{2}-\d{2})\s+(?<Time>(\d{2}:)+\d{3})\s+(?<PID>\d+)\s+(?<TID>\w+)\s+(?<Component>\w+)\s+(?<Message>.*)"
PS C:\> $out = ConvertFrom-Text -pattern $wu -path C:\Windows\WindowsUpdate.log
PS C:\> $out | group Component | Sort Count
Count Name Group
----- ---- -----
20 DtaStor {@{Date=2014-01-27; Time=07:19:19:584; PID=1...
72 Setup {@{Date=2014-01-27; Time=07:19:05:868; PID=1...
148 SLS {@{Date=2014-01-27; Time=07:19:05:086; PID=1...
150 PT {@{Date=2014-01-27; Time=07:19:08:946; PID=1...
209 WuTask {@{Date=2014-01-26; Time=20:05:28:483; PID=1...
256 EP {@{Date=2014-01-26; Time=21:21:23:341; PID=1...
263 Handler {@{Date=2014-01-27; Time=07:19:42:878; PID=3...
837 Report {@{Date=2014-01-26; Time=21:21:23:157; PID=1...
900 IdleTmr {@{Date=2014-01-26; Time=21:21:23:338; PID=1...
903 Service {@{Date=2014-01-26; Time=20:05:29:104; PID=1...
924 Misc {@{Date=2014-01-26; Time=21:21:23:033; PID=1...
1062 DnldMgr {@{Date=2014-01-26; Time=21:21:23:159; PID=1...
2544 AU {@{Date=2014-01-26; Time=19:55:27:449; PID=1...
2839 Agent {@{Date=2014-01-26; Time=21:21:23:045; PID=1...
PS C:\> $out | where {[datetime]$_.date -ge [datetime]"2/10/2014" -AND $_.component -eq "AU"} | Format-Table Date,Time,Message -wrap
Date Time Message
---- ---- -------
2014-02-10 05:36:44:183 ########### AU: Initializing Automatic Updates ###########
2014-02-10 05:36:44:184 Additional Service {117CAB2D-82B1-4B5A-A08C-4D62DBEE7782} with Approval
type {Scheduled} added to AU services list
2014-02-10 05:36:44:184 AIR Mode is disabled
2014-02-10 05:36:44:185 # Approval type: Scheduled (User preference)
2014-02-10 05:36:44:185 # Auto-install minor updates: Yes (User preference)
2014-02-10 05:36:44:185 # ServiceTypeDefault: Service 117CAB2D-82B1-4B5A-A08C-4D62DBEE7782
Approval type: (Scheduled)
2014-02-10 05:36:44:185 # Will interact with non-admins (Non-admins are elevated (User preference))
2014-02-10 05:36:44:204 WARNING: Failed to get Wu Exemption info from NLM, assuming not exempt,
error = 0x80070490
2014-02-10 05:36:44:213 AU finished delayed initialization
2014-02-10 05:38:01:000 #############
...
In this example, the WindowsUpdate log is converted from text to objects using
the regular expression pattern. Given the size of the log file this process
can take some time to complete. For example, an 11,000+ line file took 20 minutes.
.EXAMPLE
PC C:\> get-content c:\windows\windowsupdate.log -totalcount 50 | ConvertFrom-Text $wu
This example gets the first 50 lines from the Windows update log and converts
that to objects using the pattern from the previous example.
.EXAMPLE
PS C:\> $c = "(?<Protocol>\w{3})\s+(?<LocalIP>(\d{1,3}\.){3}\d{1,3}):(?<LocalPort>\d+)\s+(?<ForeignIP>.*):(?<ForeignPort>\d+)\s+(?<State>\w+)?"
PS C:\> netstat | select -skip 4 | convertfrom-text $c | format-table
Protocol LocalIP LocalPort ForeignIP ForeignPort State
-------- ------- --------- --------- ----------- -----
TCP 127.0.0.1 19872 Novo8 50835 ESTABLISHED
TCP 127.0.0.1 50440 Novo8 50441 ESTABLISHED
TCP 127.0.0.1 50441 Novo8 50440 ESTABLISHED
TCP 127.0.0.1 50445 Novo8 50446 ESTABLISHED
TCP 127.0.0.1 50446 Novo8 50445 ESTABLISHED
TCP 127.0.0.1 50835 Novo8 19872 ESTABLISHED
TCP 192.168.6.98 50753 74.125.129.125 5222 ESTABLISHED
The first command creates a variable to be used with output from the Netstat
command which is used in the second command.
.EXAMPLE
PS C:\> $arp = "(?<IPAddress>(\d{1,3}\.){3}\d{1,3})\s+(?<MAC>(\w{2}-){5}\w{2})\s+(?<Type>\w+$)"
PS C:\> arp -g | select -skip 3 | foreach {$_.Trim()} | convertfrom-text $arp
IPAddress MAC Type
--------- --- ----
172.16.10.1 00-13-d3-66-50-4b dynamic
172.16.10.100 00-0d-a2-01-07-5d dynamic
172.16.10.101 2c-76-8a-3d-11-30 dynamic
172.16.10.121 00-0e-58-ce-8b-b6 dynamic
172.16.10.122 1c-ab-a7-99-9a-e4 dynamic
172.16.10.124 00-1e-2a-d9-cd-b6 dynamic
172.16.10.126 00-0e-58-8c-13-ac dynamic
172.16.10.128 70-11-24-51-84-60 dynamic
...
The first command creates a regular expression for the ARP command. The second
prompt shows the ARP command being used to select the content, trimming each
line, and then converting the output to text using the regular expression named
pattern.
.NOTES
Last Updated: February 10, 2014
Version : 0.9
Learn more:
PowerShell in Depth: An Administrator's Guide (http://www.manning.com/jones2/)
PowerShell Deep Dives (http://manning.com/hicks/)
Learn PowerShell 3 in a Month of Lunches (http://manning.com/jones3/)
Learn PowerShell Toolmaking in a Month of Lunches (http://manning.com/jones4/)
****************************************************************
* DO NOT USE IN A PRODUCTION ENVIRONMENT UNTIL YOU HAVE TESTED *
* THOROUGHLY IN A LAB ENVIRONMENT. USE AT YOUR OWN RISK. IF *
* YOU DO NOT UNDERSTAND WHAT THIS SCRIPT DOES OR HOW IT WORKS, *
* DO NOT USE IT OUTSIDE OF A SECURE, TEST SETTING. *
****************************************************************
.LINK
https://jdhitsolutions.com/blog/2014/02/convert-text-to-object-with-powershell-and-regular-expressions
.LINK
Get-Content
About_Regular_Expressions
#>
[cmdletbinding(DefaultParameterSetname="File")]
Param(
[Parameter(Position=0,Mandatory,
HelpMessage="Enter a regular expression pattern that uses named captures")]
[ValidateScript({
if (($_.GetGroupNames() | where {$_ -notmatch "^\d{1}$"}).Count -ge 1) {
$True
}
else {
Throw "No group names found in your regular expression pattern."
}
})]
[Alias("regex")]
[regex]$Pattern,
[Parameter(Position=1,Mandatory,ParameterSetName='File')]
[ValidateScript({Test-Path $_})]
[string]$Path,
[Parameter(Position=1,Mandatory,ValueFromPipeline,ParameterSetName='Inputobject')]
[ValidateNotNullorEmpty()]
[string]$InputObject
)
Begin {
$begin=Get-Date
Write-Verbose "$((Get-Date).TimeOfDay) Starting $($MyInvocation.Mycommand)"
Write-verbose "$((Get-Date).TimeOfDay) Parameter set $($PSCmdlet.ParameterSetName)"
Write-Verbose "$((Get-Date).TimeOfDay) Using pattern $($pattern.ToString())"
#Get the defined capture names
$names = $pattern.GetGroupNames() | where {$_ -notmatch "^\d+$"}
Write-Verbose "$((Get-Date).TimeOfDay) Using names: $($names -join ',')"
#define a hashtable of parameters to splat with Write-Progress
$progParam=@{
Activity=$myinvocation.mycommand
Status = "pre-processing"
}
} #begin
Process {
If ($PSCmdlet.ParameterSetName -eq 'File') {
Write-Verbose "$((Get-Date).TimeOfDay) Processing $Path"
Try {
$progParam.CurrentOperation="Getting content from $path"
$progParam.Status="Processing"
Write-Progress @progParam
$content = Get-Content -path $path | where {$_}
} #try
Catch {
Write-Warning "Could not get content from $path. $($_.Exception.Message)"
Write-Verbose "$((Get-Date).TimeOfDay) Exiting function"
Return
}
} #if file parameter set
else {
Write-Verbose "$((Get-Date).TimeOfDay) processing input: $Inputobject"
$content = $InputObject
}
if ($content) {
Write-Verbose "$((Get-Date).TimeOfDay) processing content"
$content | foreach-object -begin {$i=0} -process {
#calculate percent complete
$i++
$pct=($i/$content.count)*100
$progParam.PercentComplete=$pct
$progParam.Status="Processing matches"
Write-Progress @progParam
#process each line of the text file
$pattern.Matches($_) |
foreach-object {
#process each match
$match = $_
Write-Verbose "$((Get-Date).TimeOfDay) processing match"
$progParam.currentoperation=$match
Write-Progress @progParam
#get named matches and create a hash table for each one
$progParam.Status = "Creating objects"
Write-Verbose "$((Get-Date).TimeOfDay) creating objects"
$hash=[ordered]@{}
foreach ($name in $names) {
$progParam.CurrentOperation=$name
Write-Progress @progParam
Write-Verbose "$((Get-Date).TimeOfDay) getting $name"
#initialize an ordered hash table
#add each name as a key to the hash table and the corresponding regex value
$hash.Add($name,$match.groups["$name"].value)
}
Write-Verbose "$((Get-Date).TimeOfDay) writing object to pipeline"
#write a custom object to the pipeline
[pscustomobject]$hash
} #foreach match
} #foreach line in the content
} #if $content
} #process
End {
Write-Verbose "$((Get-Date).TimeOfDay) Ending $($MyInvocation.Mycommand)"
$end = Get-Date
Write-Verbose "$((Get-Date).TimeOfDay) Total processing time $($end-$begin)"
} #end
} #end function
#define an optional alias
Set-Alias -Name cft -Value ConvertFrom-Text
该函数需要使用命名捕获的正则表达式模式。使用该模式,您可以指定日志文件的路径,也可以通过管道将结构化文本传递给函数。我所说的“结构化文本”是指具有可预测模式的日志文件之类的内容。或者甚至是具有一致布局的命令行工具的输出。重要的是您可以提出正则表达式模式来分析数据。如果我只想处理大型日志文件的一部分,我还希望能够通过管道输入文本。
这是使用 ARP 命令的示例。
PS C:\> $arp = "(?<IPAddress>(\d{1,3}\.){3}\d{1,3})\s+(?<MAC>(\w{2}-){5}\w{2})\s+(?<Type>\w+$)"
PS C:\> arp -g | select -skip 3 | foreach {$_.Trim()} | convertfrom-text $arp
在这个特定的示例中,我修剪 ARP 输出以删除每行中的任何前导或尾随空格,然后使用正则表达式模式将每行转换为对象。
如果您还没有明白为什么命令很有用,那么一旦我有了对象,我就可以轻松地过滤、排序、分组、导出或几乎任何其他操作。通过将日志文件转换为对象集合,我可以执行如下任务:
$wu = "(?<Date>\d{4}-\d{2}-\d{2})\s+(?<Time>(\d{2}:)+\d{3})\s+(?<PID>\d+)\s+(?<TID>\w+)\s+(?<Component>\w+)\s+(?<Message>.*)"
$out = get-content c:\windows\windowsupdate.log -totalcount 50 | ConvertFrom-Text $wu
$out | group Component | sort count
$ht = $out | group Component -AsHashTable
$ht.agent
我希望你们中的一些人尝试一下并让我知道您的想法。什么有效?缺什么?这解决了什么问题?好奇心,至少我的,想知道。享受。
猜你还喜欢
- 03-30 [玩转系统] 如何用批处理实现关机,注销,重启和锁定计算机
- 02-14 [系统故障] Win10下报错:该文件没有与之关联的应用来执行该操作
- 01-07 [系统问题] Win10--解决锁屏后会断网的问题
- 01-02 [系统技巧] Windows系统如何关闭防火墙保姆式教程,超详细
- 12-15 [玩转系统] 如何在 Windows 10 和 11 上允许多个 RDP 会话
- 12-15 [玩转系统] 查找 Exchange/Microsoft 365 中不活动(未使用)的通讯组列表
- 12-15 [玩转系统] 如何在 Windows 上安装远程服务器管理工具 (RSAT)
- 12-15 [玩转系统] 如何在 Windows 上重置组策略设置
- 12-15 [玩转系统] 如何获取计算机上的本地管理员列表?
- 12-15 [玩转系统] 在 Visual Studio Code 中连接到 MS SQL Server 数据库
- 12-15 [玩转系统] 如何降级 Windows Server 版本或许可证
- 12-15 [玩转系统] 如何允许非管理员用户在 Windows 中启动/停止服务
取消回复欢迎 你 发表评论:
- 精品推荐!
-
- 最新文章
- 热门文章
- 热评文章
[短剧] 2025年06月08日 精选+付费短剧推荐50部
[短剧] 2025年06月07日 精选+付费短剧推荐54部
[软件合集] 25年6月8日 精选软件33个
[软件合集] 25年6月7日 精选软件26个
[短剧] 2025年06月06日 精选+付费短剧推荐51部
[电影] 死神来了 1-6合集 4K HDR 杜比视界 外挂双语字幕
[软件合集] 25年6月6日 精选软件64个
[影视] 黑道中人 Alto Knights(2025)剧情 犯罪 历史 电影
[古装剧] [七侠五义][全75集][WEB-MP4/76G][国语无字][1080P][焦恩俊经典]
[实用软件] 虚拟手机号 电话 验证码 注册
[短剧] 2025年06月07日 精选+付费短剧推荐54部
[剧集] [央视][笑傲江湖][2001][DVD-RMVB][高清][40集全]李亚鹏、许晴、苗乙乙
[电视剧] 欢乐颂.5部全 (2016-2024)
[电视剧] [突围] [45集全] [WEB-MP4/每集1.5GB] [国语/内嵌中文字幕] [4K-2160P] [无水印]
[影视] 【稀有资源】香港老片 艺坛照妖镜之96应召名册 (1996)
[剧集] 神经风云(2023)(完结).4K
[剧集] [BT] [TVB] [黑夜彩虹(2003)] [全21集] [粤语中字] [TV-RMVB]
[软件合集] 25年6月6日 精选软件64个
[实用软件] 虚拟手机号 电话 验证码 注册
[资源] B站充电视频合集,包含多位重量级up主,全是大佬真金白银买来的~【99GB】
[电视剧] [突围] [45集全] [WEB-MP4/每集1.5GB] [国语/内嵌中文字幕] [4K-2160P] [无水印]
[短剧] 2025年06月07日 精选+付费短剧推荐54部
[软件合集] 25年6月6日 精选软件64个
[剧集] [央视][笑傲江湖][2001][DVD-RMVB][高清][40集全]李亚鹏、许晴、苗乙乙
[电影] 美国队长4 4K原盘REMUX 杜比视界 内封简繁英双语字幕 49G
[电影] 死神来了(1-6)大合集!
[软件合集] 25年05月13日 精选软件16个
[精品软件] 25年05月15日 精选软件18个
[绝版资源] 南与北 第1-2季 合集 North and South (1985) /美国/豆瓣: 8.8[1080P][中文字幕]
[软件] 25年05月14日 精选软件57个
- 最新评论
-
- 热门tag