捕获正则表达式匹配项以从查找表中进行替换

时间:2018-12-13 19:23:00

标签: regex powershell

我正在PowerShell中编写语言解释器(对于那些可能感兴趣的人来说,语言是PILOT),现在我已经实现了变量替换。变量名由$#组成,后跟[A-Za-z0-9]中最多十个字符。但是,如果变量名以\为前缀,则应被替换。据我所知,我要匹配的模式是[^\\][\$#]\w{,10},但是我不清楚如何将匹配结果存储在PowerShell变量中,以便我可以查找变量名在表中替换为它的值。

例如,如果powershell变量$expr包含字符串\#Foo has the value #Foo,而$vartable["#Foo"]包含值5,则需要捕获#Foo-仅第二个-在$ varname中,然后用$ vartable [$ varname]替换捕获的#Foo-$expr -replace "[^\\][\$#]\w{,10}",$vartable[$varname]应该产生\#Foo has the value 5

我是否正确计算了模式,如何捕获匹配?

(我应该注意,我正在使用PowerShell 5.1进行开发,但是希望它能够在该版本或更高版本中运行,包括非Windows操作系统上的PSCore。)

1 个答案:

答案 0 :(得分:1)

[^\\]模式通常 不是检查字符是否转义的有效方法,因为也可以转义反斜杠来表示文字反斜杠char。例如,\\#Foo具有一个未转义的变量,必须根据原始要求进行匹配。有效的方法是使用(?<=(?<!\\)(?:\\{2})*)兼容.NET的后向匹配项,该匹配项与立即在其前面加上任意数量的偶​​数反斜杠而不是反斜杠的位置匹配。

接下来,您不能在字符串替换模式内使用代码。您可以在[regex]::Replace内部使用回调,也可以-从PowerShell Core v6.1开始-您可以使用脚本块作为-replace的替换参数:

[regex]::Replace($s,'(?<=(?<!\\)(?:\\{2})*)[$#]\w{1,10}\b', {param($match) $vartable[$match.Value] })

或(PowerShell Core v6.1 +):

$s -replace '(?<=(?<!\\)(?:\\{2})*)[$#]\w{1,10}\b', { $vartable[$_.Value] }