我正在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。)
答案 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] }