我有一个xml文件,其中有一些行
<!--<__AMAZONSITE id="-123456780" instance ="CATZ00124"__/>-->
我需要该行中的id和实例值。
我需要在两个不同的变量中分别包含-123456780
和CATZ00124
。
下面是我尝试过的示例代码
$xmlfile = 'D:\Test\sample.xml'
$find_string = '__AMAZONSITE'
$array = @((Get-Content $xmlfile) | select-string $find_string)
Write-Host $array.Length
foreach ($commentedline in $array)
{
Write-Host $commentedline.Line.Split('id=')
}
我得到的结果如下:
<!--<__AMAZONSITE
"-123456780"
nstance
"CATZ00124"__/>
答案 0 :(得分:1)
首选方法仍然是对XML文件使用XML工具。
只要文件中包含AMAZONSITE和instance的行是唯一的,就可以这样做:
## Q:\Test\2019\09\13\SO_57923292.ps1
$xmlfile = 'D:\Test\sample.xml' # '.\sample.xml' #
## see following RegEx live and with explanation on https://regex101.com/r/w34ieh/1
$RE = '(?<=AMAZONSITE id=")(?<id>[\d-]+)" instance ="(?<instance>[^"]+)"'
if((Get-Content $xmlfile -raw) -match $RE){
$AmazonSiteID = $Matches.id
$Instance = $Matches.instance
}
答案 1 :(得分:0)
LotPings' answer明智地建议将regular expression与capture groups结合使用,以从每个匹配行中提取感兴趣的子字符串。
您可以将其合并到用于单管道解决方案的Select-String
调用中(假设所关注的XML注释都在一行中):
# Define the regex to use with Select-String, which both
# matches the lines of interest and captures the substrings of interest
# ('id' an 'instance' attributes) via capture groups, (...)
$regex = '<!--<__AMAZONSITE id="(.+?)" instance ="(.+?)"__/>-->'
Select-String -LiteralPath $xmlfile -Pattern $regex | ForEach-Object {
# Output a custom object with properties reflecting
# the substrings of interest reported by the capture groups.
[pscustomobject] @{
id = $_.Matches.Groups[1].Value
instance = $_.Matches.Groups[2].Value
}
}
结果是一个自定义对象的数组,每个对象都有一个.id
和.instance
属性,它们具有感兴趣的值(最好设置单个变量);在控制台中,输出看起来像这样:
id instance
-- --------
-123456780 CATZ00124
-123456781 CATZ00125
-123456782 CATZ00126
关于您尝试过的事情:
注意:我正在讨论您对.Split()
的使用,尽管出于您的意图提取子字符串 的目的,.Split()
并不是最好的工具只是隔离感兴趣的子字符串的第一步。
如LotPings在注释中所述,在Windows PowerShell中,$commentedline.Line.Split('id=')
使String.Split()
方法将输入字符串除以任何单个字符字符串'id='
,因为 Windows PowerShell 选择takes a char[]
value的方法重载,即字符数组,这不是您的意图
您可以通过强制使用overload that accepts string[]
(即使您仅传递一个字符串)来纠正此问题,如下所示:一个选项参数:
$commentedline.Line.Split([string[] 'id=', 'None') # OK, splits by whole string
请注意,在PowerShell Core 中,逻辑是相反的 ,因为.NET Core引入了new overload with just [string]
(带有 Optional options参数),默认情况下由PowerShell Core选择。相反,这意味着如果您要做要在PowerShell Core中按任意字符进行拆分,则必须将拆分的字符串强制转换为[char[]]
。
一般来说, PowerShell具有-split
operator ,它是基于 regex 的,并且比{{1} } -参见this answer。
适用于您的情况:
String.Split()
$commentedline.Line -split 'id='
将id=
解释为 regex ,由于字符串不包含regex元字符(具有特殊含义的字符),因此此处没有区别;如果您确实希望使用 literal 子字符串进行安全拆分,请使用-split
作为RHS。
请注意,[regex]::Escape('...')
默认情况下不区分大小写 ,就像PowerShell通常一样;但是,您可以使用-split
变体来区分大小写 。