PowerShell正则匹配URL下划线后无法完成替换问题求助
替换XLF文件中URL的下划线为
%95 我需要遍历双语XLF文件,检测<trans-unit>的<source>节点里带下划线的URL,把下划线替换成%95(适配第三方工具规则,无法修改工具)。我试过正则((https?://\S*?)_([^)\s]*?))能匹配目标URL,但代码没法替换URL里所有下划线,尝试了两段代码都有问题:
原尝试代码1(仅替换单个下划线)
function ReplaceUnderscoresInURLs($xlfContent) { foreach ($transUnit in $xlfContent.xliff.file.body.'trans-unit') { $sourceNode = $transUnit.source $matches = [regex]::Matches($sourceNode.InnerXml, '\((https?://[^\s"]*?)_([^)\s]*?)\)') foreach ($match in $matches) { $matchedLink = $match.Groups[0].Value $matchedLinkReplaced = $matchedLink -replace '_', '%95' $sourceNode.InnerXml = $sourceNode.InnerXml -replace [regex]::Escape($matchedLink), $matchedLinkReplaced } } return $xlfContent }
问题:正则每次仅匹配含单个下划线的片段,循环处理时无法覆盖URL内所有下划线,导致替换不彻底。
原尝试代码2(错误删除内容)
function ReplaceUnderscoresInParentheses($xlfContent) { $xlfContent = $xlfContent -replace '(?<=\()\S*_(?=\S*?\))', '%95' return $xlfContent }
问题:正则逻辑错误,会删除第一个下划线之前的所有内容,破坏URL结构。
解决方案
方案1:使用正则回调函数批量替换
直接匹配括号内的完整URL,在回调中替换所有下划线:
function ReplaceUnderscoresInURLs($xlfContent) { foreach ($transUnit in $xlfContent.xliff.file.body.'trans-unit') { $sourceNode = $transUnit.source # 匹配括号内的完整HTTP/HTTPS URL $sourceNode.InnerXml = [regex]::Replace($sourceNode.InnerXml, '\((https?://[^)]+)\)', { param($match) # 提取URL并替换所有下划线为%95 $url = $match.Groups[1].Value $replacedUrl = $url -replace '_', '%95' return "($replacedUrl)" }) } return $xlfContent }
优势:一次性处理完整URL,确保所有下划线都被替换,代码简洁高效。
方案2:改进遍历匹配逻辑(倒序处理)
如果需要保留遍历节点的逻辑,可通过倒序处理匹配结果避免位置偏移:
function ReplaceUnderscoresInURLs($xlfContent) { foreach ($transUnit in $xlfContent.xliff.file.body.'trans-unit') { $sourceNode = $transUnit.source # 匹配所有括号内的HTTP/HTTPS URL $matches = [regex]::Matches($sourceNode.InnerXml, '\((https?://[^)]+)\)') # 倒序处理,防止替换后影响后续匹配位置 for ($i = $matches.Count - 1; $i -ge 0; $i--) { $match = $matches[$i] $fullMatch = $match.Groups[0].Value $url = $match.Groups[1].Value $replacedUrl = $url -replace '_', '%95' $replacedFullMatch = "($replacedUrl)" # 替换指定位置的内容 $sourceNode.InnerXml = $sourceNode.InnerXml.Substring(0, $match.Index) + $replacedFullMatch + $sourceNode.InnerXml.Substring($match.Index + $fullMatch.Length) } } return $xlfContent }
优势:精准控制替换位置,适合复杂XML节点场景。
测试示例
使用提供的XLF文件测试后,<trans-unit id="3">的<source>内容会从:
<source>Lorem Ipsum 3 with [Link](https://example.com/with_underscore)</source>
变为:
<source>Lorem Ipsum 3 with [Link](https://example.com/with%95underscore)</source>
内容的提问来源于stack exchange,提问作者Hateforms
相关产品推荐
相关产品推荐

