温馨提示:本文翻译自stackoverflow.com,查看原文请点击:scripting - How can I filter out text twice in Powershell?
powershell scripting

scripting - 如何在Powershell中过滤两次文本?

发布于 2020-04-19 13:48:52

我有一个Powershell脚本,该脚本返回的输出接近我想要的输出,但是我需要删除一些行和HTML样式的标签。我已经有以下代码可以过滤掉:

get-content "atxtfile.txt" | select-string -Pattern '<fields>' -Context 1

但是,如果我尝试将该输出传递给Second "select-string",则不会得到任何结果。我在网上查看REGEX示例,但是我所看到的大部分内容都涉及使用编码循环来实现其目标。我更习惯于Linux shell,在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>描述符之间的所有内容,但是我基本上需要<fullName>没有XML标记行。

查看更多

提问者
murkywaters
被浏览
77
mklement0 2018-04-17 02:39

最简单的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>元素)作为阵列

这种访问集合上属性并将其隐式应用于集合元素的功能(将结果收集到数组中)是一种通用的PSv3 +功能,称为成员枚举


作为一个替代方案,可以考虑使用Select-Xml小命令,这(在PSV2太可用)支持的XPath查询通常允许更复杂的提取逻辑(虽然不严格这里不需要); Select-Xml[xml].NET类型.SelectNodes()方法的高级包装
以下与上述解决方案等效:

$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

注意:

与点符号不同,使用时必须考虑XML名称空间Select-Xml

鉴于其<CustomObject>所有后代都在xmlns通过URI标识的命名空间中http://soap.force.com/2006/04/metadata,您必须:

  • 您作为参数传递哈希表中定义此名称空间-Namespace
    • 警告:默认名称空间xmlns是特殊的,因为它不能用作哈希表中的键;而是选择一个任意的键名,例如ns,但是请确保使用所选的键名作为节点名前缀(请参阅下一点)。
  • 在XPath查询中的所有节点名称前面加上名称空间名称,然后加上:例如,ns:CustomObject