再次审查这个问题后,我添加了第二个示例,我希望它能突出显示我的困惑被放大的地方,即有一个通过其索引 (1) 访问的捕获组,而我期望的值碰巧也是$filecontent
1 。
此问题表明,在引用其他变量时,可以使用反引号来寻址双引号字符串中的捕获组。
如果您需要在替换表达式中引用其他变量(您可能会这样做),您可以使用双引号字符串并使用反引号转义捕获美元
然而,我看到了一些我无法解释的有趣行为。
$VersionReplacementRegex = "(\d+\.)\d+" #capture first digit + dot b/c I want to keep it
$BuildVersionValidationRegex = "\d+\.\d+\.\d+"
$VersionData = [regex]::matches("some-18.11.8",$BuildVersionValidationRegex)
$NewVersion = $VersionData[0] #matches 18.11.8
$filecontent = "stuff 1.0.0.0 other stuff" #Get-Content($file)
Run Code Online (Sandbox Code Playgroud)
$filecontent
使用链接问题中指定的捕获组替换文本会产生不完整的结果...
$filecontent -replace $VersionReplacementRegex, "`$1$NewVersion" | Write-Host
Run Code Online (Sandbox Code Playgroud)
回报:118.11.8
预期:1.18.11.8
$1
但是在和之间添加空格$NewVersion
会产生不同但同样无益的结果。
$filecontent -replace $VersionReplacementRegex, "`$1 $NewVersion" | Write-Host
Run Code Online (Sandbox Code Playgroud)
返回:1. 18.11.8
捕获的点出现在这里,但不需要的空间也出现。
对于此示例,结果有些相似,但捕获组似乎得到了错误的值。
$NewVersion = 18.11.8
$filecontent = "stuff 5.0.0.0 other stuff"
$filecontent -replace "(\d+\.)\d+", "`$1$NewVersion" | Write-Host
# returns: 118.11.8
# expected: 5.18.11.8
Run Code Online (Sandbox Code Playgroud)
在替换字符串中添加空格将返回:5. 18.11.8
那么,我错过了什么,或者有更好的方法吗?
从过去的经验来看,在对该问题的评论中提供关键线索的PetSerAl不会回来发表答案。
太长了;博士
如果您使用-replace
引用捕获组和 PowerShell变量的替换操作数,请使用诸如 的语法"`${<ndx>}${<PsVar>}"
,其中<ndx>
是捕获组的索引,<PsVar>
是 PowerShell 变量的名称;请注意第一个`
之前的内容$
:
PS> $var = '2'; 'foo' -replace '(f)', "[`${1}$var]"
[f2]oo # OK, -replace saw '${1}2'
Run Code Online (Sandbox Code Playgroud)
如果您忽略使用{...}
来消除捕获组索引的歧义,则替换会发生故障,因为插值字符串值随后会有效地引用不同的索引:-replace
then see [$12]
,由于引用了带有索引 的不存在的捕获组12
,因此保持原样:
PS> $var = '2'; 'foo' -replace '(f)', "[`$1$var]"
[$12]oo # !! -replace saw '$12', i.e., a nonexistent group with index 12
Run Code Online (Sandbox Code Playgroud)
将 PowerShell 的字符串扩展-replace
(插值)与运算符的语法混合起来很棘手,因为很容易混淆:
在双引号( "..."
) 字符串中,PowerShell 的通用字符串扩展(字符串插值)功能首先解释$
字符,其中前缀引用 (PowerShell)变量以及内部的整个语句。$
$(...)
无论该扩展的结果是什么字符串,都会由运算符进行解释-replace
,其中$
- 前缀标记指的是正则表达式匹配操作的结果,如本答案中所总结的。
请注意,这些解释层$
完全无关,并且两者都使用印记这一事实$
是偶然的。
所以:
如果您的替换操作数不需要字符串扩展,即不需要引用 PowerShell变量或表达式,请务必使用单引号字符串 ( '...'
),这样 PowerShell 的字符串扩展就不会发挥作用:
PS> 'foo' -replace '(f)', '[$1]'
[f]oo # OK - if you had used "[$1]" instead, the output would be '[]oo',
# because $1 is then interpreted as a *PowerShell variable*.
Run Code Online (Sandbox Code Playgroud)如果您确实需要涉及字符串扩展:
前缀$
字符。应该传递-replace
给`
`
(反引号)是 PowerShell 的通用转义字符,在"..."
字符串中它用于指示下一个字符要按字面意思处理;放在 a 之前$
,它会抑制该标记的字符串插值;例如,"I'm `$HOME"
产生字面量I'm $HOME
,即变量引用没有扩展。为了消除对捕获组的引用的歧义,例如$1
,,将它们括在{...}
- 例如,${1}
{...}
来消除PowerShell变量名称的歧义;例如"$HOME1"
必须是"${HOME}1"
为了引用变量$HOME
成功引用变量。"..."
基于替换的操作数中,始终使用{...}
捕获组索引/名称(和 PS 变量)是一个好习惯。如果有疑问,请单独输出替换操作数以检查-replace
最终会看到什么。
"[`$1$var]"
应用字符串插值步骤的自身输出会使问题更加明显:[$12]
为了说明后一点:
PS> $var = '2'; 'foo' -replace '(f)', "[`$1$var]"
[$12]oo # !! $1 wasn't recognizes as the 1st capture group.
Run Code Online (Sandbox Code Playgroud)
问题是-replace
,在字符串扩展之后,将 视为[$12]
替换操作数,并且由于没有带有索引的捕获组12
,因此它保持原样。
将捕获组编号括起来可以{...}
解决问题:
PS> $var = '2'; 'foo' -replace '(f)', "[`${1}$var]"
[f2]oo # OK
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
839 次 |
最近记录: |