在 powershell 脚本中使用正则表达式替换 key/value 标签的值
using regex in powershell script to replace value of a key/value tags
使用 powershell 脚本,我需要更新 xml 文件中的一些值。 xml 是键和值的列表。
更具体地说,我需要查找密钥 "servername" 并使用 $myservername 更新相关值标签。还要查找密钥 "serverport" 并使用 $myport.
更新相关值标签
如何使用 powershell 脚本完成此操作?
我想到使用简单的正则表达式替换命令如下
$myservername = "some-server"
$myport = "8888"
$localFile = "C:\_Temp\Files190822115503\Manifest.xml"
$content = (Get-Content $localFile)
$newcontent = $content -replace '"<Key>servername</Key>\s*<Value>(value1)</Value>"', $myservername
$newcontent = $content -replace '"<Key>serverport</Key>\s*<Value>(value1)</Value>"', $myport
以下只是 xml 文件的一部分:
<Properties>
<ManifestProperty ValueType="string">
<Key>servername</Key>
<Value>value1</Value>
</ManifestProperty>
<ManifestProperty ValueType="string">
<Key>serverport</Key>
<Value>value2</Value>
</ManifestProperty>
</Properties>
我们需要搜索 "key" 然后替换 "value"
如果将文件作为 XmlDocument 对象读入 PowerShell,您可以执行以下操作:
$myservername = "some-server"
$myport = "8888"
$xml = [xml](Get-Content C:\temp\xml.xml)
$xml.SelectNodes("//Properties/ManifestProperty[Key = 'servername']") |
Foreach-Object {
$_.Value = $myservername
}
$xml.SelectNodes("//Properties/ManifestProperty[Key = 'serverport']") |
Foreach-Object {
$_.Value = $myport
}
$xml.Save("C:\Temp\xml.xml")
访问 XML 对象的属性将比正则表达式替换更可靠。
解释:
代码使用 [xml]
类型加速器将 C:\temp\xml.xml
的内容转换为 XmlDocument 对象。 SelectNodes()
方法使用 XPath 查找 Properties
的任何子元素,其中 ManifestProperty
元素包含 Key
节点。该节点必须包含文本 servername
或文本 serverport
。以防万一该方法 returns 多个节点,结果将通过管道传输到 Foreach-Object
以更新所有值。
//Properties/ManifestProperty[Key = 'servername']
查找属于 Properties
元素子元素且至少包含一个名为 Key
且值为 [=19 的子元素的所有 ManifestProperty
元素=].
如果你必须使用正则表达式来替换文本字符串,我不建议这样做,你可以执行以下操作:
$myservername = "some-server"
$myport = "8888"
$xml = Get-Content xml.xml -Raw
$xml = $xml -replace "(?s)(?<=<Key>servername</Key>.*?<Value>)value1(?=</Value>)",$myservername
$xml = $xml -replace "(?s)(?<=<Key>serverport</Key>.*?<Value>)value2(?=</Value>)",$myport
正则表达式替换说明:
Get-Content xml.xml -Raw
:将文件内容作为一个字符串读取。这很有用,因为我们需要匹配多行。删除 -Raw
开关,将文件作为数组读入 PowerShell。对于数组输出,我们不能使用正则表达式来读后读或读前读。
(?s)
:这是单行修饰符。它允许正则表达式 .
匹配任何换行符。这对于跨多行匹配特别有用。
(?<=<Key>servername</Key>.*?<Value>)
:对字面匹配<Key>servername</Key>
执行肯定的lookbehind断言(?<=)
,非贪婪匹配0个或多个字符,字面匹配<Value>
.
value1
:文字匹配
(?=</Value>)
:对文字匹配执行肯定的先行断言</Value>
。
下面是使用捕获组进行正则表达式替换的另一种方法:
$myservername = "some-server"
$myport = "8888"
$xml = Get-Content xml.xml -Raw
$xml = $xml -replace "(?s)(?<NameKey><Key>servername</Key>.*?<Value>)value1(?<NameValue></Value>)","`${NameKey}$myservername`${NameValue}"
$xml = $xml -replace "(?s)(?<PortKey><Key>serverport</Key>.*?<Value>)value2(?<PortValue></Value>)","`${PortKey}$myport`${PortValue}"
正则表达式替换说明:
Get-Content xml.xml -Raw
:将文件内容作为一个字符串读取。这很有用,因为我们需要匹配多行。删除 -Raw
开关,将文件作为数组读入 PowerShell。对于数组输出,我们不能使用正则表达式来读后读或读前读。
(?s)
:这是单行修饰符。它允许正则表达式 .
匹配任何换行符。这对于跨多行匹配特别有用。
(?<PortKey><Key>serverport</Key>.*?<Value>)
:(?<PortKey>)
创建一个名为 PortKey
的捕获组。括号内匹配的所有内容都将包含在该捕获中。 serverport
字面匹配。 .*?
是0个或多个字符的惰性匹配。 <Value>
字面匹配。
value2
:文字匹配
(?<PortValue></Value>)
:为括号内匹配的所有内容捕获名为 PortValue
的组。 </Value>
是文字匹配。
"`${PortKey}$myport`${PortValue}"
:这是替换字符串。请注意表达式周围的双引号,以便对 $myport
进行插值。 ${PortKey}
和 ${PortValue}
是访问捕获组所需的语法。反引号字符用于转义那些捕获组引用中的 $
,因为我们不希望 PowerShell 插入它们。
您通常不需要命名您的捕获组。但是,由于其中一个捕获是数字的,这可能会导致访问默认捕获组时出现问题。 </code> 将访问第一个捕获组。由于 <code>$myport
是一个数字,因此 `$myport
将被计算为 888
并且正则表达式匹配将没有名为 18888
的捕获组。所以命名捕获组,增加了更好的可预测性。
使用 powershell 脚本,我需要更新 xml 文件中的一些值。 xml 是键和值的列表。
更具体地说,我需要查找密钥 "servername" 并使用 $myservername 更新相关值标签。还要查找密钥 "serverport" 并使用 $myport.
更新相关值标签如何使用 powershell 脚本完成此操作?
我想到使用简单的正则表达式替换命令如下
$myservername = "some-server"
$myport = "8888"
$localFile = "C:\_Temp\Files190822115503\Manifest.xml"
$content = (Get-Content $localFile)
$newcontent = $content -replace '"<Key>servername</Key>\s*<Value>(value1)</Value>"', $myservername
$newcontent = $content -replace '"<Key>serverport</Key>\s*<Value>(value1)</Value>"', $myport
以下只是 xml 文件的一部分:
<Properties>
<ManifestProperty ValueType="string">
<Key>servername</Key>
<Value>value1</Value>
</ManifestProperty>
<ManifestProperty ValueType="string">
<Key>serverport</Key>
<Value>value2</Value>
</ManifestProperty>
</Properties>
我们需要搜索 "key" 然后替换 "value"
如果将文件作为 XmlDocument 对象读入 PowerShell,您可以执行以下操作:
$myservername = "some-server"
$myport = "8888"
$xml = [xml](Get-Content C:\temp\xml.xml)
$xml.SelectNodes("//Properties/ManifestProperty[Key = 'servername']") |
Foreach-Object {
$_.Value = $myservername
}
$xml.SelectNodes("//Properties/ManifestProperty[Key = 'serverport']") |
Foreach-Object {
$_.Value = $myport
}
$xml.Save("C:\Temp\xml.xml")
访问 XML 对象的属性将比正则表达式替换更可靠。
解释:
代码使用 [xml]
类型加速器将 C:\temp\xml.xml
的内容转换为 XmlDocument 对象。 SelectNodes()
方法使用 XPath 查找 Properties
的任何子元素,其中 ManifestProperty
元素包含 Key
节点。该节点必须包含文本 servername
或文本 serverport
。以防万一该方法 returns 多个节点,结果将通过管道传输到 Foreach-Object
以更新所有值。
//Properties/ManifestProperty[Key = 'servername']
查找属于Properties
元素子元素且至少包含一个名为Key
且值为 [=19 的子元素的所有ManifestProperty
元素=].
如果你必须使用正则表达式来替换文本字符串,我不建议这样做,你可以执行以下操作:
$myservername = "some-server"
$myport = "8888"
$xml = Get-Content xml.xml -Raw
$xml = $xml -replace "(?s)(?<=<Key>servername</Key>.*?<Value>)value1(?=</Value>)",$myservername
$xml = $xml -replace "(?s)(?<=<Key>serverport</Key>.*?<Value>)value2(?=</Value>)",$myport
正则表达式替换说明:
Get-Content xml.xml -Raw
:将文件内容作为一个字符串读取。这很有用,因为我们需要匹配多行。删除-Raw
开关,将文件作为数组读入 PowerShell。对于数组输出,我们不能使用正则表达式来读后读或读前读。(?s)
:这是单行修饰符。它允许正则表达式.
匹配任何换行符。这对于跨多行匹配特别有用。(?<=<Key>servername</Key>.*?<Value>)
:对字面匹配<Key>servername</Key>
执行肯定的lookbehind断言(?<=)
,非贪婪匹配0个或多个字符,字面匹配<Value>
.value1
:文字匹配(?=</Value>)
:对文字匹配执行肯定的先行断言</Value>
。
下面是使用捕获组进行正则表达式替换的另一种方法:
$myservername = "some-server"
$myport = "8888"
$xml = Get-Content xml.xml -Raw
$xml = $xml -replace "(?s)(?<NameKey><Key>servername</Key>.*?<Value>)value1(?<NameValue></Value>)","`${NameKey}$myservername`${NameValue}"
$xml = $xml -replace "(?s)(?<PortKey><Key>serverport</Key>.*?<Value>)value2(?<PortValue></Value>)","`${PortKey}$myport`${PortValue}"
正则表达式替换说明:
Get-Content xml.xml -Raw
:将文件内容作为一个字符串读取。这很有用,因为我们需要匹配多行。删除-Raw
开关,将文件作为数组读入 PowerShell。对于数组输出,我们不能使用正则表达式来读后读或读前读。(?s)
:这是单行修饰符。它允许正则表达式.
匹配任何换行符。这对于跨多行匹配特别有用。(?<PortKey><Key>serverport</Key>.*?<Value>)
:(?<PortKey>)
创建一个名为PortKey
的捕获组。括号内匹配的所有内容都将包含在该捕获中。serverport
字面匹配。.*?
是0个或多个字符的惰性匹配。<Value>
字面匹配。value2
:文字匹配(?<PortValue></Value>)
:为括号内匹配的所有内容捕获名为PortValue
的组。</Value>
是文字匹配。"`${PortKey}$myport`${PortValue}"
:这是替换字符串。请注意表达式周围的双引号,以便对$myport
进行插值。${PortKey}
和${PortValue}
是访问捕获组所需的语法。反引号字符用于转义那些捕获组引用中的$
,因为我们不希望 PowerShell 插入它们。
您通常不需要命名您的捕获组。但是,由于其中一个捕获是数字的,这可能会导致访问默认捕获组时出现问题。 </code> 将访问第一个捕获组。由于 <code>$myport
是一个数字,因此 `$myport
将被计算为 888
并且正则表达式匹配将没有名为 18888
的捕获组。所以命名捕获组,增加了更好的可预测性。