gpt4 book ai didi

powershell - 避免模​​ block 中的变量被调用者覆盖,反之亦然

转载 作者:行者123 更新时间:2023-12-03 21:57:51 24 4
gpt4 key购买 nike

我正在 Powershell 中构建一个自定义模块来分解一些代码。

在模块中的函数中,我使用了变量。但是,如果调用者使用相同的变量名,它可能会干扰我的模块。

例如,这里有一个小模块 (MyModule.psm1):

function Get-Foo{
param(
[int]$x,
[int]$y
)

try{
$result = $x/$y

} catch{
Write-Warning "Something get wrong"
}
if($result -ne 0){
Write-Host "x/y = $result"
}
}

Export-ModuleMember -Function "Get-Foo"

以及使用该模块的示例脚本:

Import-Module "$PSScriptRoot\MyModule\MyModule.psm1" -Force

$result = 3 # some other computation

Get-Foo -x 42 -Y 0

输出是:

x/y = 3

如您所见,调用者声明的变量名称与我的模块中的名称冲突。

避免这种行为的最佳做法是什么?

作为一项要求,我必须假设模块的开发人员不会是主要的脚本开发人员。因此,模块的内部不应该是已知的(有点像黑盒子)

最佳答案

Ivan Mirchev's helpful answer , robdy's helpful answerAdminOfThings对问题的评论提供了关键的指示;让我总结和补充它们:

  • 在你的函数中,一个本地 $result如果参数变量 $y 则永远不会创建变量包含 0 ,因为被零除会导致语句终止错误(触发 catch block )。

  • 没有本地 $result变量,在祖先作用域中定义的变量可能是可见的(父作用域、祖父作用域...),这要归功于 PowerShell 的动态作用域.

    • 在你的情况下,$result是在全局范围中定义的,模块也可以看到,因此您的模块函数可以看到那个值。

      • 但是,请注意分配$result通过该名称隐式创建一个本地变量,而不是修改祖先变量。 一旦在本地创建,变量遮盖同名的祖先变量;也就是说,它会隐藏它,除非您在定义它的范围内明确引用它。
    • 另请注意,模块的设计不会看到来自模块外部调用者的变量其他而不是全局范围,例如如果您的模块是从一个脚本

    • 参见 this answer有关 PowerShell 范围的更多信息。


解决方案:

  • 初始化局部变量$result在你的函数开始时以保证它的存在——见下文。

  • 或者,显式引用局部变量 - 我提到这些选项主要是为了完整性和说明基本概念,我认为它们不实用:

    • 您可以使用范围说明符$local: ,在 $y 的情况下正在0会导致$local:result引用一个不存在变量(除非您在除法失败之前已经初始化了它),PowerShell 默认为 $null :

      • if ($null -ne $local:result) { Write-Host "x/y = $result" }

      • 警告:如果 Set-StrictMode -Version 1或更高版本有效,对不存在变量的引用会导致语句终止错误(这意味着函数/脚本作为一个整体将默认在下一条语句处继续执行)。

    • 一种独立于严格模式但冗长且较慢的替代方法是使用 Get-Variable 显式测试局部变量是否存在的 cmdlet:

      • if (Get-Variable -ErrorAction Ignore -Scope Local result) { Write-Host "x/y = $result" }

初始化 == 预先创建局部变量的解决方案:

function Get-Foo{
param(
[int]$x,
[int]$y
)

# Initialize and thereby implicitly create
# $result as a local variable.
$result = 0

try{
$result = $x/$y
} catch{
Write-Warning "Something get wrong"
}
# If the division failed, $result still has its initial value, 0
if($result -ne 0){
Write-Host "x/y = $result"
}
}

关于powershell - 避免模​​ block 中的变量被调用者覆盖,反之亦然,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58319077/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com