我是PowerShell的新手,这似乎是一种合理的方法来替换我的DLL中的内部版本号(通过修改.rc文件)和我的SVN存储库中的修订号。
使用PowerShell ISE,我创建了以下变量:
$1 = "123"
$revision = "230"
现在我正在使用以下命令测试我的字符串替换,以查看它与我在线阅读的行为方式。我期待找到一些可以回复12,3,0,230
的文件版本的东西:
$pattern = '(^\s*FILEVERSION\s*[0-9]+,[0-9]+,[0-9]+,)[0-9]+$'
' FILEVERSION 12,3,0,0' -replace $pattern, "`$1"
# returns " FILEVERSION 12,3,0,"
' FILEVERSION 12,3,0,0' -replace $pattern, "$1"
# returns "123"
' FILEVERSION 12,3,0,0' -replace $pattern, '$1'
# returns " FILEVERSION 12,3,0,"
' FILEVERSION 12,3,0,0' -replace $pattern, "`$1$revision"
# returns "$1230"
' FILEVERSION 12,3,0,0' -replace $pattern, "`$1`$revision"
# returns " FILEVERSION 12,3,0,$revision"
' FILEVERSION 12,3,0,0' -replace $pattern, "$revision`$1"
# returns "230 FILEVERSION 12,3,0,"
我对尝试4和6的结果感到惊讶。尝试4,为什么PowerShell不会用" 230"替换$revision
?同样尝试6,为什么在`$1
之前它被正确替换?我在替换字符串中查找了有关反引号的范围的信息,但没有找到任何内容。
答案 0 :(得分:5)
在替换操作中,PowerShell首先展开PowerShell变量,然后将匹配和替换字符串移交给正则表达式引擎。因此,替换字符串"`$1$revision"
扩展为"$1230"
并传递给regexp引擎。由于没有第1230个被捕获的组被扩展,因此反向引用保持原样。
要避免此问题,请将反向引用标识符放在大括号中:
'FILEVERSION 12,3,0,0' -replace '...', "`${1}$revision"
确保您的替换字符串包含反向引用$1
和字符串230
。
关于其他方法正在做什么的说明(为了完整性):
' FILEVERSION 12,3,0,0' -replace '...', "`$1"
返回" FILEVERSION 12,3,0,"
因为整个匹配被替换为第一个捕获组的反向引用而没有别的。
' FILEVERSION 12,3,0,0' -replace '...', "$1"
返回"123"
因为PowerShell在传递给regexp引擎之前扩展变量 $1
。后者只看到字符串"123"
。
' FILEVERSION 12,3,0,0' -replace '...', '$1'
与第一种方法相同的行为(单引号阻止PowerShell扩展变量$1
,就像转义$
一样。
' FILEVERSION 12,3,0,0' -replace '...', "`$1`$revision"
返回" FILEVERSION 12,3,0,$revision"
因为两个$
都已转义,因此PowerShell不会展开$revision
,而正则表达式引擎$revision
只是一个普通的字符串。< / p>
' FILEVERSION 12,3,0,0' -replace '...', "$revision`$1"
返回"230 FILEVERSION 12,3,0,"
,因为PowerShell会扩展$revision
,但这次该值位于反向引用之前,因此regexp引擎可以将$1
扩展到第一个捕获的组。