我有一个HTML文件,显示安装在计算机上的软件,我想删除HTML文件中表格中的一些单元格。 以下是代码示例:
<tr><td>Adobe Acrobat Reader DC</td><td>18.009.20050</td><td>20171130</td><td>kratos.kcprod1.com</td><td>4104917a-93f2-46e5-941a-c4efd54504b7</td><td>True</td></tr>
<tr><td>Adobe Flash Player 28 ActiveX</td><td>28.0.0.137</td><td></td><td>kratos.kcprod1.com</td><td>4104917a-93f2-46e5-941a-c4efd54504b7</td><td>True</td></tr>
......等等。
我想要完成的是从td标记的第4个实例开始删除所有内容,并在每行的结束/ tr标记之前停止,这基本上消除了......
<td>kratos.kcprod1.com</td><td>4104917a-93f2-46e5-941a-c4efd54504b7</td><td>True</td>
<td>kratos.kcprod1.com</td><td>4104917a-93f2-46e5-941a-c4efd54504b7</td><td>True</td>
......所以我离开了...
<tr><td>Adobe Acrobat Reader DC</td><td>18.009.20050</td><td>20171130</td></tr>
<tr><td>Adobe Flash Player 28 ActiveX</td><td>28.0.0.137</td><td></td></tr>
我正在使用的正则表达式是
(?<=<td>)(.*)(?=<\/tr>)
我遇到的问题是上面的正则表达式选择了enitre代码行。如何更改它以便从每行的第4个标记实例开始?
请参阅以下链接,其中包含我正在使用的HTML文件的完整示例以及所应用的正则表达式:https://regex101.com/r/C9lkMc/3
编辑1:此HTML是从PowerShell脚本生成的,用于在远程计算机上获取已安装的软件。代码是:
Invoke-Command -ComputerName $hostname -ScriptBlock {
if (!([Diagnostics.Process]::GetCurrentProcess().Path -match '\\syswow64\\')) {
$unistallPath = "\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\"
$unistallWow6432Path = "\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\"
@(
if (Test-Path "HKLM:$unistallWow6432Path" ) { Get-ChildItem "HKLM:$unistallWow6432Path"}
if (Test-Path "HKLM:$unistallPath" ) { Get-ChildItem "HKLM:$unistallPath" }
if (Test-Path "HKCU:$unistallWow6432Path") { Get-ChildItem "HKCU:$unistallWow6432Path"}
if (Test-Path "HKCU:$unistallPath" ) { Get-ChildItem "HKCU:$unistallPath" }
) |
ForEach-Object { Get-ItemProperty $_.PSPath } |
Where-Object {
$_.DisplayName -and !$_.SystemComponent -and !$_.ReleaseType -and !$_.ParentKeyName -and ($_.UninstallString -or $_.NoRemove)
} |
Sort-Object DisplayName | Select-Object -Property DisplayName, DisplayVersion, InstallDate | ft
}
}
答案 0 :(得分:1)
正则表达式对于解析HTML并不是很好;可能会有很多奇怪的场景;例如如果您有一个节点<td />
或<td colspan="2">
,您预计会有<td>
,会发生什么?同样,HTML(恼人地)并不总是遵循XML规则;所以XML解析器不起作用(例如<hr>
没有结束标记/ <hr />
被视为无效)。
因此,如果解析HTML,理想情况下需要使用HTML解析器。为此,PowerShell可以访问HtmlFile
com对象,在此处记录:https://msdn.microsoft.com/en-us/library/aa752574(v=vs.85).aspx
以下是一些例子......
此代码查找所有TR元素,然后在前4个后删除所有TD并返回行的外部HTML。
$html = @'
some sort of html code
<hr> an unclosed tab so it's messy like html / unlike xml
<table>
<tr><th>Program Name</th><th>version</th><th>install date</th><th>computer name</th><th>ID</th><th>Installed</th></tr>
<tr><td>Adobe Acrobat Reader DC</td><td>18.009.20050</td><td>20171130</td><td>kratos.kcprod1.com</td><td>4104917a-93f2-46e5-941a-c4efd54504b7</td><td>True</td></tr>
<tr><td>Adobe Flash Player 28 ActiveX</td><td>28.0.0.137</td><td></td><td>kratos.kcprod1.com</td><td>4104917a-93f2-46e5-941a-c4efd54504b7</td><td>True</td></tr>
<tr><td /><td>123</td><td></td><td>hello.com</td><td>456</td><td>True</td></tr>
</table>
etc...
'@
$Parser = New-Object -ComObject 'HTMLFile' #see https://msdn.microsoft.com/en-us/library/aa752574(v=vs.85).aspx
$Parser.IHTMLDocument2_write($html) #if you're using PS4 or below use instead: $Parser.IHTMLDocument2_write($html)
$parser.documentElement.getElementsByTagName('tr') | %{
$tr = $_
$tr.getElementsByTagName('td') | select-object -skip 4 | %{$tr.removeChild($_)} | out-null
$tr.OuterHtml
}
这以类似的方式工作;但只是拉回每行前4个单元格的值:
$html = @'
some sort of html code
<hr> an unclosed tab so it's messy like html / unlike xml
<table>
<tr><th>Program Name</th><th>version</th><th>install date</th><th>computer name</th><th>ID</th><th>Installed</th></tr>
<tr><td>Adobe Acrobat Reader DC</td><td>18.009.20050</td><td>20171130</td><td>kratos.kcprod1.com</td><td>4104917a-93f2-46e5-941a-c4efd54504b7</td><td>True</td></tr>
<tr><td>Adobe Flash Player 28 ActiveX</td><td>28.0.0.137</td><td></td><td>kratos.kcprod1.com</td><td>4104917a-93f2-46e5-941a-c4efd54504b7</td><td>True</td></tr>
<tr><td /><td>123</td><td></td><td>hello.com</td><td>456</td><td>True</td></tr>
</table>
etc...
'@
$Parser = New-Object -ComObject 'HTMLFile' #see https://msdn.microsoft.com/en-us/library/aa752574(v=vs.85).aspx
$Parser.IHTMLDocument2_write($html) #if you're using PS4 or below use instead: $Parser.IHTMLDocument2_write($html)
$parser.documentElement.getElementsByTagName('tr') | %{
$tr = $_
$a,$b,$c,$d = $tr.getElementsByTagName('td') | select-object -first 4 | %{"$($_.innerText)"} #we do this istead of `select -expand innerText` to ensure nulls are returned as blanks; not ignored
(New-Object -TypeName 'PSObject' -Property ([ordered]@{
AppName = $a
Version = $b
InstallDate = $c
ComputerName = $d
}))
}