【问题标题】:Powershell regex for replacing text between two strings用于替换两个字符串之间的文本的 Powershell 正则表达式
【发布时间】:2021-03-29 02:37:45
【问题描述】:

我正在尝试使用 powershell 脚本更改两个字符串之间的密码,我遇到了两个问题。

  1. 一个复杂的密码似乎会破坏我的正则表达式,如果我使用像“TestPassword”这样简单的东西,那么正则表达式就会达到我的预期。但是使用更复杂的密码 "6QAfD5PmMhWzUxTq1FO1bGJQQXRXu6tizN29h6MRUSI=" 它会中断并导致
SSLEnabled="true" keystoreFile="C:\cert.pfx" $16QAfD5PmMhWzUxTq1FO1bGJQQXRXu6tizN29h6MRUSI=" keystoreType="PKCS12"/>

而不是

SSLEnabled="true" keystoreFile="C:\cert.pfx" keystorePass="6QAfD5PmMhWzUxTq1FO1bGJQQXRXu6tizN29h6MRUSI=" keystoreType="PKCS12"/>
  1. 我希望对第二个匹配组不那么具体,例如,此时我必须指定 '" keystoreType' 但我希望不那么具体,只指定结束引号。这样,如果我更改将来的 keystoreType 参数我不必担心更改正则表达式以适应。

Bellow 是我的 powershell:

#Set new password in server.xml
$pass='6QAfD5PmMhWzUxTq1FO1bGJQQXRXu6tizN29h6MRUSI='
$server_xml=".\server.xml"
(Get-Content $server_xml) -replace '(keystorePass=")(.*)(" keystoreType)',('$1{0}$3' -f "$pass") | Set-Content $server_xml

下面是我的 xml 的摘录:

<Connector port="443" relaxedPathChars="[]|" relaxedQueryChars="[]|{}^&#x5c;&#x60;&quot;&lt;&gt;"
                   maxThreads="150" minSpareThreads="25" connectionTimeout="20000" enableLookups="false"
                   maxHttpHeaderSize="8192" protocol="HTTP/1.1" useBodyEncodingForURI="true" redirectPort="8443"
                   acceptCount="100" disableUploadTimeout="true" bindOnInit="false" secure="true" scheme="https"
                   proxyName="test.example.com" proxyPort="443"
                   SSLEnabled="true" keystoreFile="C:\cert.pfx" keystorePass="123abc" keystoreType="PKCS12"/>

【问题讨论】:

  • 您也可以考虑使用 xml 解析器。

标签: regex xml powershell


【解决方案1】:

解析

正如 cmets 中的 @the four bird@codextor 所指出的那样;使用字符串方法(如-Replace)直接窥视和戳入serialized 字符串(如XML)是一个坏主意。相反,您应该使用相关的解析器进行搜索和替换,它具有更简单的语法,可以解决您的问题和其他陷阱(例如双引号 $pass='Test"123')。

安全

忽略相关的解析器甚至会带来潜在的安全风险,因为用户(假设只允许提供密码)可以通过提供如下密码在您的xml(连接器)中注入一个新属性:

$pass = 'MyPass" maxParameterCount="0'

示例

$Xml = [Xml]'<Connector port="443" relaxedPathChars="[]|" relaxedQueryChars="[]|{}^&#x5c;&#x60;&quot;&lt;&gt;" maxThreads="150" minSpareThreads="25" connectionTimeout="20000" enableLookups="false" maxHttpHeaderSize="8192" protocol="HTTP/1.1" useBodyEncodingForURI="true" redirectPort="8443" acceptCount="100" disableUploadTimeout="true" bindOnInit="false" secure="true" scheme="https" proxyName="test.example.com" proxyPort="443" SSLEnabled="true" keystoreFile="C:\cert.pfx" keystorePass="123abc" keystoreType="PKCS12"/>'

$Xml.Connector.keystorePass = '6QAfD5PmMhWzUxTq1FO1bGJQQXRXu6tizN29h6MRUSI='

$Xml.Connector

port                  : 443
relaxedPathChars      : []|
relaxedQueryChars     : []|{}^\`"<>
maxThreads            : 150
minSpareThreads       : 25
connectionTimeout     : 20000
enableLookups         : false
maxHttpHeaderSize     : 8192
protocol              : HTTP/1.1
useBodyEncodingForURI : true
redirectPort          : 8443
acceptCount           : 100
disableUploadTimeout  : true
bindOnInit            : false
secure                : true
scheme                : https
proxyName             : test.example.com
proxyPort             : 443
SSLEnabled            : true
keystoreFile          : C:\cert.pfx
keystorePass          : 6QAfD5PmMhWzUxTq1FO1bGJQQXRXu6tizN29h6MRUSI=
keystoreType          : PKCS12

$Xml.OuterXml

<Connector port="443" relaxedPathChars="[]|" relaxedQueryChars="[]|{}^\`&quot;&lt;&gt;" maxThreads="150" minSpareThreads="25" connectionTimeout="20000" enableLookups="false" maxHttpHeaderSize="8192" protocol="HTTP/1.1" useBodyEncodingForURI="true" redirectPort="8443" acceptCount="100" disableUploadTimeout="true" bindOnInit="false" secure="true" scheme="https" proxyName="test.example.com" proxyPort="443" SSLEnabled="true" keystoreFile="C:\cert.pfx" keystorePass="6QAfD5PmMhWzUxTq1FO1bGJQQXRXu6tizN29h6MRUSI=" keystoreType="PKCS12" />

附录

(基于 cmets 中的附加信息)

如果您的xml 中有更多连接器,例如:

$Xml = [Xml]'
    <Connectors>
        <Connector
            port="80"
            keystorePass="Pass1" />
        <Connector
            port="443"
            keystorePass="Pass2" />
    </Connectors>'

您可以像这样处理连接器:

$Xml.Connectors.Connector[0].keystorePass = 'Pass80'
$Xml.Connectors.Connector.Where{ $_.port -eq '443' }.SetAttribute('keystorePass', 'Pass443')

$Xml.OuterXml

<Connectors><Connector port="80" keystorePass="Pass80" /><Connector port="443" keystorePass="Pass443" /></Connectors>

【讨论】:

  • 这看起来确实是一个不易出错且更简洁的解决方案。例如,如果有多个连接器怎么办?其中一些可能被注释掉并且不包含密码字段。
【解决方案2】:

这个人有一个类似的问题,我可以在我的代码中使用正则表达式:

Hide passwords in string

我最终得到了以下结果:

#Set new password in server.xml
$pass='6QAfD5PmMhWzUxTq1FO1bGJQQXRXu6tizN29h6MRUSI='
$server_xml=".\server.xml"
(Get-Content $server_xml) -replace '(?:(?<=keystorePass=")\S+(?="))',("$pass") | Set-Content $server_xml

【讨论】:

  • 很高兴您能够找到可行的解决方案。但我建议您考虑在 PowerShell 中将 server.xml 文件作为 XML 对象读取,然后遍历它的节点树。这样您就不必依赖正则表达式,这可以减少代码中出错的可能性。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-26
  • 1970-01-01
  • 2010-09-23
  • 2014-12-08
  • 2014-06-24
  • 1970-01-01
相关资源
最近更新 更多