我有一个Powershell脚本返回了一个接近我想要的输出,但是我需要删除一些行和HTML样式的标记。我已经有以下代码来过滤掉:
get-content "atxtfile.txt" | select-string -Pattern '<fields>' -Context 1
但是,如果我尝试将该输出传输到第二个"select-string"
,我将不会得到任何结果。我在网上查看了REGEX示例,但我见过的大部分内容都涉及使用编码循环来实现其目标。我更习惯于Linux shell,你可以将输出管道输出到多个greps
来过滤掉文本。有没有办法用PowerShell实现相同的东西或类似的东西?这是我正在按要求使用的文件:
<?xml version="1.0" encoding="UTF-8"?>
<CustomObject xmlns="http://soap.force.com/2006/04/metadata">
<actionOverrides>
<actionName>Accept</actionName>
<type>Default</type>
</actionOverrides>
<actionOverrides>
<actionName>CancelEdit</actionName>
<type>Default</type>
</actionOverrides>
<actionOverrides>
<actionName>Today</actionName>
<type>Default</type>
</actionOverrides>
<actionOverrides>
<actionName>View</actionName>
<type>Default</type>
</actionOverrides>
<compactLayoutAssignment>SYSTEM</compactLayoutAssignment>
<enableFeeds>false</enableFeeds>
<fields>
<fullName>ActivityDate</fullName>
</fields>
<fields>
<fullName>ActivityDateTime</fullName>
</fields>
<fields>
<fullName>Guid</fullName>
</fields>
<fields>
<fullName>Description</fullName>
</fields>
</CustomObject>
所以,我只希望<fullName>
描述符之间的文本到目前为止我有以下内容:
get-content "txtfile.txt" | select-string -Pattern '<fields>' -Context 1
这将为我提供<fields>
描述符之间的所有内容,但是我基本上需要没有XML标记的<fullName>
行。
答案 0 :(得分:2)
最简单的 PSv3 +解决方案是使用PowerShell的内置XML DOM支持,这使得XML文档的节点可作为对象层次结构访问 点符号 :
PS> ([xml] (Get-Content -Raw txtfile.txt)).CustomObject.fields.fullName
ActivityDate
ActivityDateTime
Guid
Description
请注意即使.fields
是数组 - 代表顶级元素<fields>
的所有子<CustomObject>
元素 - .fullName
,应用于它并将所有数组元素(<fullName>
元素)中的子元素<field>
的值作为数组返回。
能够访问集合上的属性并将其隐式应用于集合的元素,并将结果收集到数组,是一个名为member enumeration的通用PSv3 +功能。
作为替代,请考虑使用 Select-Xml
cmdlet (也可在PSv2中使用),支持XPath queries 通常允许更复杂的提取逻辑(虽然这里不是严格要求的); Select-Xml
是围绕[xml]
.NET类型.SelectNodes()
method的高级包装器。
以下是上述解决方案的等效内容:
$namespaces = @{ ns="http://soap.force.com/2006/04/metadata" }
$xpathQuery = '/ns:CustomObject/ns:fields/ns:fullName'
(Select-Xml -LiteralPath txtfile.txt $xpathQuery -Namespace $namespaces).Node.InnerText
注意:
与点符号不同,使用Select-Xml
时必须考虑 XML命名空间。
鉴于<CustomObject>
及其所有后代都在名称空间xmlns
中,通过URI http://soap.force.com/2006/04/metadata
标识,您必须:
-Namespace
参数
xmlns
的特殊之处在于不能用作哈希表中的键;相反,选择任意键名称,例如ns
,但请务必使用所选键名作为节点名称前缀(参见下一点)。:
,为XPath查询中的所有节点名称添加前缀;例如,ns:CustomObject
答案 1 :(得分:1)
确定。所以,如果你有那个文件,那么:
[xml]$xml = Get-Content atextfile.txt
$xml.CustomObject.fields | select fullname
答案 2 :(得分:1)
mklement0为问题提供了最佳解决方案。 但要回答有关使用Select-String过滤文本两次的问题。
如果我们将Select-String
的结果导入Out-String -Stream
,我们可以再次将其传递给Select-String
。
这可以在一行上完成,但我使用变量来尝试使其更具可读性。
$Match = Get-Content "atxtfile.txt" | Select-String -Pattern '<fields>' -Context 1
$Match | Out-String -Stream | Select-String -Pattern "Guid"
如果我们将$match
传递给Get-Member
,我们会发现一些有趣的属性。
$Match.Matches.Value
这将显示<fields>
的所有实例(模式匹配)。
$Matches.Context.PostContext
$Matches.Context.PreContext
这将包含<fields>
之前和之后的行(前后的上下文)。