PowerShell:在字符串中使用未声明的变量
PowerShell: Use undeclared variable in string
我想知道如何在字符串中使用未声明的变量。这是一个演示我的问题的简化示例
[string]$sentence="My dog is $age years old"
[int]$age = 6
$sentence | write-output
$age = 3
$sentence | write-output
寻找这个输出:
My dog is 6 years old
My dog is 3 years old
获取此输出:
My dog is years old
My dog is years old
我试过以下方法:
"My dog is `$age years old" #My dog is $age years old
$("My dog is `$age years old") #My dog is $age years old
$("My dog is $age years old") #My dog is 3 years old
有没有办法让它更紧凑?或者这是唯一的方法?
编辑:我注意到重点是字符串。我将在出现问题的地方分享我的代码。我需要将一堆从 20 行到 2000 行不等的 VBS 脚本(>40)迁移到 Powershell
VBS 文件:
Function InitializeApp
Dim sPath
...
End function
Powershell 脚本:
$vbs=Get-Content -path $path #get content in array, one line per index
$rules=
@(
[pscustomobject]@{
"name"="func_start";
"vbs" = 'Function (?<V1>\w*)'; # The regex named group V1 will initialized when match is found
"ps" = {"Function () `{`n"} # Group V1 is to be inserted in replacement string
}
)
function Invoke-TestAndReplace($line,$ruleName){
$r_vbs=$($rules.where({$_.name -eq $ruleName}).vbs) # Function (?<V1>\w*)
$r_ps=$($rules.where({$_.name -eq $ruleName}).ps) # {"Function () `{`n"}
if( $regex = ($line | select-string -pattern $r_vbs )) {
[=15=]=$regex[0].Matches.Groups.Where({$_.name -eq "0"}).value # Function InitializeApp
=$regex[0].Matches.Groups.Where({$_.name -eq "V1"}).value # InitializeApp
=$regex[0].Matches.Groups.Where({$_.name -eq "V2"}).value #
$r_ps = & $r_ps # Function InitializeApp() {
$replace = $line.replace([=15=],$r_ps) # Function InitializeApp -> Function InitializeApp() {
} else {$replace = $line} #keep old value
return $replace
}
$newVBS=@()
foreach($line in $vbs){
$line = Invoke-TestAndReplace -line $line -rulename "func_start"
}
此答案显示了 . You can use a Script Block 的一种过于复杂的替代方法,用于存储表达式(包括您的 $age
变量)然后执行它。
$sentence = { "My dog is $age years old" }
$age = 6
& $sentence | write-output # => My dog is 6 years old
$age = 3
& $sentence | write-output # => My dog is 3 years old
如果您希望脚本块“记住”变量创建时的值,您可以使用它 .GetNewClosure()
method,例如:
$expressions = foreach($i in 0..5) {
{ "Value of `$i was $i in this iteration" }.GetNewClosure()
}
$expressions.foreach{ & $_ }
我不知道如何使用插值来做到这一点,但我可以使用旧的 .Net String.Format()
方法来做到这一点,如下所示:
$sentence = "My dog is {0} years old."
$age = 6
[string]::Format($sentence, $age) | Write-Output
# => My dog is 6 years old
$age = 3
[string]::Format($sentence, $age) | Write-Output
# => My dog is 3 years old
[string]::Format($sentence, 12) | Write-Output
# => My dog is 12 years old
我们可以这样缩短(感谢评论者):
$sentence = "My dog is {0} years old."
$age = 6
Write-Output ($sentence -f $age)
# => My dog is 6 years old
$age = 3
Write-Output ($sentence -f $age)
# => My dog is 3 years old
Write-Output ($sentence -f 12)
# => My dog is 12 years old
另请注意模板字符串中的不同占位符。
您可以使用ExpandString
$sentence = 'My dog is $age years old.'
$age = 4
$ExecutionContext.InvokeCommand.ExpandString($sentence)
# My dog is 4 years old.
$age = 5
$ExecutionContext.InvokeCommand.ExpandString($sentence)
# My dog is 5 years old.
您也可以定义一个函数并调用该函数
function sentence([int]$age) {
"My dog is $age years old"
}
1..5 | ForEach-Object { sentence -age $_ }
# My dog is 1 years old
# My dog is 2 years old
# My dog is 3 years old
# My dog is 4 years old
# My dog is 5 years old
我想知道如何在字符串中使用未声明的变量。这是一个演示我的问题的简化示例
[string]$sentence="My dog is $age years old"
[int]$age = 6
$sentence | write-output
$age = 3
$sentence | write-output
寻找这个输出:
My dog is 6 years old
My dog is 3 years old
获取此输出:
My dog is years old
My dog is years old
我试过以下方法:
"My dog is `$age years old" #My dog is $age years old
$("My dog is `$age years old") #My dog is $age years old
$("My dog is $age years old") #My dog is 3 years old
有没有办法让它更紧凑?或者这是唯一的方法?
编辑:我注意到重点是字符串。我将在出现问题的地方分享我的代码。我需要将一堆从 20 行到 2000 行不等的 VBS 脚本(>40)迁移到 Powershell
VBS 文件:
Function InitializeApp
Dim sPath
...
End function
Powershell 脚本:
$vbs=Get-Content -path $path #get content in array, one line per index
$rules=
@(
[pscustomobject]@{
"name"="func_start";
"vbs" = 'Function (?<V1>\w*)'; # The regex named group V1 will initialized when match is found
"ps" = {"Function () `{`n"} # Group V1 is to be inserted in replacement string
}
)
function Invoke-TestAndReplace($line,$ruleName){
$r_vbs=$($rules.where({$_.name -eq $ruleName}).vbs) # Function (?<V1>\w*)
$r_ps=$($rules.where({$_.name -eq $ruleName}).ps) # {"Function () `{`n"}
if( $regex = ($line | select-string -pattern $r_vbs )) {
[=15=]=$regex[0].Matches.Groups.Where({$_.name -eq "0"}).value # Function InitializeApp
=$regex[0].Matches.Groups.Where({$_.name -eq "V1"}).value # InitializeApp
=$regex[0].Matches.Groups.Where({$_.name -eq "V2"}).value #
$r_ps = & $r_ps # Function InitializeApp() {
$replace = $line.replace([=15=],$r_ps) # Function InitializeApp -> Function InitializeApp() {
} else {$replace = $line} #keep old value
return $replace
}
$newVBS=@()
foreach($line in $vbs){
$line = Invoke-TestAndReplace -line $line -rulename "func_start"
}
此答案显示了 $age
变量)然后执行它。
$sentence = { "My dog is $age years old" }
$age = 6
& $sentence | write-output # => My dog is 6 years old
$age = 3
& $sentence | write-output # => My dog is 3 years old
如果您希望脚本块“记住”变量创建时的值,您可以使用它 .GetNewClosure()
method,例如:
$expressions = foreach($i in 0..5) {
{ "Value of `$i was $i in this iteration" }.GetNewClosure()
}
$expressions.foreach{ & $_ }
我不知道如何使用插值来做到这一点,但我可以使用旧的 .Net String.Format()
方法来做到这一点,如下所示:
$sentence = "My dog is {0} years old."
$age = 6
[string]::Format($sentence, $age) | Write-Output
# => My dog is 6 years old
$age = 3
[string]::Format($sentence, $age) | Write-Output
# => My dog is 3 years old
[string]::Format($sentence, 12) | Write-Output
# => My dog is 12 years old
我们可以这样缩短(感谢评论者):
$sentence = "My dog is {0} years old."
$age = 6
Write-Output ($sentence -f $age)
# => My dog is 6 years old
$age = 3
Write-Output ($sentence -f $age)
# => My dog is 3 years old
Write-Output ($sentence -f 12)
# => My dog is 12 years old
另请注意模板字符串中的不同占位符。
您可以使用ExpandString
$sentence = 'My dog is $age years old.'
$age = 4
$ExecutionContext.InvokeCommand.ExpandString($sentence)
# My dog is 4 years old.
$age = 5
$ExecutionContext.InvokeCommand.ExpandString($sentence)
# My dog is 5 years old.
您也可以定义一个函数并调用该函数
function sentence([int]$age) {
"My dog is $age years old"
}
1..5 | ForEach-Object { sentence -age $_ }
# My dog is 1 years old
# My dog is 2 years old
# My dog is 3 years old
# My dog is 4 years old
# My dog is 5 years old