PowerShell正则替换中如何在捕获变量$slot插入字符
AOS6配置命令转AOS7:接口格式修改问题
我需要把AOS 6配置里的接口命令转换成AOS 7格式,具体是把 interfaces 2/6 alias "TOTO" 改成 interfaces 2/1/6 alias "TOTO"。
一开始我用了下面的PowerShell命令,能匹配到目标行但没法修改接口段的格式:
'interfaces 2/6 alias "TOTO"' -replace '^interfaces (?<slot>[0-9]/[0-9]{1,2}) alias "(?<alias>[_a-zA-Z0-9]+)"$','interfaces port ${slot} alias "${alias}"'
我尝试在替换的时候修改捕获到的$slot变量,插入1/让它变成2/1/6,写了下面的代码但没成功:
'interfaces 1/6 alias "TOTO"' -replace '^interfaces (?<slot>[0-9]/[0-9]{1,2}) alias "(?<alias>[_a-zA-Z0-9]+)"$','interfaces port $($slot.insert(2,"1/")) alias "$alias"'
我的完整代码如下:
param($confAOS6Path=$null) if($confAOS6Path -eq $null){ $confAOS6Path = Read-Host "Entrer le chemin du fichier AOS verion 6" } $confAOS6 = Get-Content $confAOS6Path $matchList = [PSCustomObject]@{ '^interfaces (?<slot>[0-9]/[0-9]{1,2}) alias "(?<alias>[_a-zA-Z0-9]+)"$' = 'interfaces port $($slot.insert(2,"1/")) alias "$alias"' } foreach($line in $confAOS6){ foreach($regex in $matchList.PSObject.Properties.Name){ if($line -match $regex){ Invoke-Expression '$line -replace $regex,$matchList.$regex' } else{ Add-Content -path "test.txt" -Value $line } } }
现在需要解决的是:怎么在-replace的替换逻辑里修改捕获到的$slot变量,实现插入1/的效果?
解决方案
方法1:拆分正则分组直接重组
最直接的方式是把原来的slot拆成两个独立分组(槽位号和端口号),在替换字符串里直接拼接1/,不需要额外修改变量:
单条测试命令:
'interfaces 2/6 alias "TOTO"' -replace '^interfaces (?<chassis>[0-9])/(?<port>[0-9]{1,2}) alias "(?<alias>[_a-zA-Z0-9]+)"$','interfaces ${chassis}/1/${port} alias "${alias}"'
对应修改你的完整代码里的matchList:
$matchList = [PSCustomObject]@{ '^interfaces (?<chassis>[0-9])/(?<port>[0-9]{1,2}) alias "(?<alias>[_a-zA-Z0-9]+)"$' = 'interfaces ${chassis}/1/${port} alias "${alias}"' }
方法2:用脚本块做替换(PowerShell 3.0及以上支持)
如果需要更灵活的字符串处理逻辑,可以用脚本块作为-replace的第二个参数,在脚本块里直接操作捕获到的分组内容:
修改循环里的处理逻辑,同时去掉不安全的Invoke-Expression:
foreach($line in $confAOS6){ $isModified = $false foreach($regex in $matchList.PSObject.Properties.Name){ if($line -match $regex){ $newLine = $line -replace $regex, { # 从匹配结果里取出slot和alias $originalSlot = $matches['slot'] # 在slot的第2位插入"1/" $newSlot = $originalSlot.Insert(2, '1/') # 返回拼接后的新行 return "interfaces port $newSlot alias `"$($matches['alias'])`"" } Add-Content -path "test.txt" -Value $newLine $isModified = $true break } } # 没匹配到的行直接写入 if(-not $isModified){ Add-Content -path "test.txt" -Value $line } }
对应的matchList可以只保留正则规则,不需要存替换字符串:
$matchList = [PSCustomObject]@{ '^interfaces (?<slot>[0-9]/[0-9]{1,2}) alias "(?<alias>[_a-zA-Z0-9]+)"$' = $null }
注意点
原代码里的Invoke-Expression存在安全风险,而且容易因为字符串转义出问题,上面的两种方法都不需要使用它,直接处理更可靠。
内容的提问来源于stack exchange,提问作者totouser
相关产品推荐
相关产品推荐

