解决PowerShell Replace替换时替换字符串自动换行问题
解决PowerShell批量替换UTF-16LE文本时标签换行的问题
问题背景
现有一个23718行、编码为**UTF-16 LE with BOM (Unicode)**的文本文件,通过批处理调用PowerShell CLI执行文本替换:为所有包含Weapon_AssaultRifle_.*_DisplayName=且未添加颜色标签的行包裹指定颜色代码,已有标签或值为空的行保持不变。
使用的批处理代码如下:
powershell -NoProfile -Command ^ "Write-Host modifying InventoryItemTypes.GER...;" ^ "$file = '%target%\InventoryItemTypes.GER';" ^ "$content = (Get-Content -Raw -Encoding UTF8 $file);" ^ "$content -Replace '(?m)(Weapon_AssaultRifle_.*_DisplayName)=\b(?!<color:.*>.*</color>\b)(.+)$', '$1=<color:R=1 G=1 B=0>$2</color>' |" ^ "Set-Content -Encoding Unicode -NoNewLine $file"
实际执行后出现异常:替换后的</color>被强制换行,示例结果如下:
InventoryItemTypes_Weapon_AssaultRifle_ATAC_DisplayName=<color:R=1 G=1 B=0>ATAC 424 </color>
但该正则在regex101测试时无换行问题。
待处理文本片段示例:
... InventoryItemTypes_Weapon_AssaultRifle_STAR_Slot3_Valentines_Leased_CreatorName=Amorous Marketplace InventoryItemTypes_Weapon_AssaultRifle_STAR_Slot3_Valentines_Leased_DisplayName=<color:R=1 G=0.45 B=1>STAR 556 'Love-Gun'</color> InventoryItemTypes_Weapon_AssaultRifle_Star-LCR_PR1_Joker_CreatorName=Joker Distribution InventoryItemTypes_Weapon_AssaultRifle_Star-LCR_PR1_Joker_DisplayName=STAR 556 'LCR' PR1 ...
问题原因
- 编码不匹配:原文件是UTF-16LE编码,但
Get-Content用UTF8编码读取,导致文件中的换行符(CRLF)被错误解析,正则中的$(行尾匹配)定位错位,最终让替换后的标签被拆分到新行。 - 正则匹配范围模糊:
(.+)在(?m)模式下理论上匹配行尾前的所有字符,但编码解析错误会让部分换行相关字符被纳入匹配内容,干扰替换逻辑。
解决方案
修正后的批处理代码
powershell -NoProfile -Command ^ "Write-Host modifying InventoryItemTypes.GER...;" ^ "$file = '%target%\InventoryItemTypes.GER';" ^ "$content = (Get-Content -Raw -Encoding Unicode $file);" ^ "$content -Replace '(?m)(Weapon_AssaultRifle_.*_DisplayName)=\b(?!<color:.*>.*</color>\b)([^\r\n]+)$', '$1=<color:R=1 G=1 B=0>$2</color>' |" ^ "Set-Content -Encoding Unicode -NoNewLine $file"
关键修改点
- 统一编码读取:将
Get-Content的-Encoding UTF8改为-Encoding Unicode(PowerShell中Unicode编码对应UTF-16LE带BOM),确保文件内容(包括换行符)被正确解析。 - 精确匹配行内容:将正则中的
(.+)替换为([^\r\n]+),明确匹配行尾前不包含换行符的所有字符,避免因编码问题导致的匹配范围错误。
验证效果
修正后,目标行将被正确替换为单行格式:
InventoryItemTypes_Weapon_AssaultRifle_ATAC_DisplayName=<color:R=1 G=1 B=0>ATAC 424</color>
已有颜色标签的行和空值行将保持原内容不变。
内容的提问来源于stack exchange,提问作者leiseg
相关产品推荐
相关产品推荐

