PowerShell:无法使用变量变量 $Using:(Get-Variable -Name $Name)

PowerShell: Unable to use a variable variable $Using:(Get-Variable -Name $Name)

提问人:Thor1012 提问时间:10/27/2023 最后编辑:mklement0Thor1012 更新时间:10/27/2023 访问量:83

问:

在 ForEach-Object -Parallel{} 中,我尝试调用在函数之前定义了不同名称的变量。这需要从函数外部拉入变量。$Using:Name

但是,当尝试使用 或 它提供错误时:“变量引用无效。 ”:“后跟的不是有效的变量名称字符。请考虑使用 ${} 来分隔名称。$Using:$Name$Using:(Get-Variable -Name $Name)

尝试使用 时,给出文本字符串并且不起作用。 其他试图使其工作的变体要么提供相同的变量引用无效,要么变量为 null。${Using:$Name}{}

尝试过的变化:

$Using:{(Get-Variable -Name $Name)}
$Using:(Get-Variable -Name $Name)
Get-Variable -Name "Using:$Name"
Get-Variable -Name Using:$Name

代码示例:

$0IndexA = @(45,51,57)
$1IndexA = @(1490,1901,1903)

0..1 | Foreach-Object -Parallel {
    $ParallelNumber = $_ # Used for readability

    For ($c = 0; $c -le (Get-Variable $ParallelNumber"IndexA").value.count; $c++){
        Get-Variable -Name $ParallelNumber"IndexA"[$c]
    }
}

错误:找不到名为“0IndexA”的变量。

尝试使用 -scope 1 错误:“作用域编号”1“超过活动作用域的数量。(参数“范围”)实际值为1。

使用 间接 foreach-object PowerShell 并行处理

评论

3赞 Mathias R. Jessen 10/27/2023
在哪里定义?请共享重现问题的代码:)$Name
0赞 Thor1012 10/27/2023
0..1 |ForEach-Object <#-ThrottleLimit 5#> -parallel { $Name = ([string]($Using:1IndexA[1])+“A”) $Using:(Get-Variable -Name $Name) } $Using:1IndexA[1])+“A” - 这成功返回字符串“1901A”进行测试。是的,我知道上面的代码没有利用 ForEach-Object 组件,我有一个更大的函数,但这就是错误所在。
1赞 Darin 10/27/2023
我想我明白你的问题是什么,不确定你是否可以完成你想做的事情,但你可以尝试通过使用以下方式访问HashTable:$HashVars = @{a = 123; b = 234; c = 345}; 'a', 'b', 'c' | Foreach-Object -Parallel { ($using:HashVars)[$_] }
1赞 ArcSet 10/27/2023
你能提供可重现的代码吗?您在评论中的上述代码此后没有任何作用。
1赞 mclayton 10/27/2023
的语法是 ,not - 它需要一个裸变量名称,而不是计算结果为包含变量名称的字符串的表达式 - 请参阅 learn.microsoft.com/en-us/powershell/module/...。如果您需要按表达式引用值,您可以使用 @Darin 的哈希表建议作为解决方法......$using$using:<VariableName>$using:<expression>

答:

3赞 mklement0 10/27/2023 #1

您正在寻找变量间接,即通过存储在另一个变量中的名称间接引用变量的能力

但是,在 $using: 作用域的上下文中,不支持此操作后面的内容必须文本变量名称。:

正如 Darin 所建议的,解决方法是在调用方的作用域中使用一个哈希表,将输入对象映射到要用于它们的值:

# Helper hashtable that maps each input to ForEach-Object -Parallel
# to values to use with that input.
$valuesHash = @{
  0 = @(45,51,57)
  1 = @(1490,1901,1903)
}

0..1 | Foreach-Object -Parallel {
  $values = ($using:valuesHash)[$_]
  "$values" # sample output; -> '45 51 57', '1490 1901 1903'
}

请注意,需要将引用括起来,以便对其应用索引 ()。[1]$using:(...)[$_]


[1] 可以说,这应该不是必需的,但从 PowerShell 7.3.9 开始 - 请参阅 GitHub 问题 #10876 进行讨论。

评论

0赞 Darin 10/27/2023
仅供参考:由于他使用的是数值,因此数组数组也是一种选择:$IndexA = @(@(45,51,57), @(1490,1901,1903)); 0..1 | Foreach-Object -Parallel { $ParallelNumber = $_; For ($c = 0; $c -le ($Using:IndexA)[$_].Count; $c++) { ($Using:IndexA)[$_][$c] } }
1赞 mklement0 10/27/2023
好点子,Darin,但这是一个非常具体的场景(以输入开头的连续数字)。相比之下,基于哈希表的方法应该适用于任何输入对象。0
0赞 zdan 10/27/2023 #2

@mkelement答案似乎是一个很好的解决方案。如果这对您不起作用,另一种解决方法是使用作业而不是 ,这样您就可以将变量作为输入参数传递。Foreach-Object -Parallel

我重新制作了您的示例以证明:

$0IndexA = @(45,51,57)
$1IndexA = @(1490,1901,1903)


$parJobs = 0..1 | foreach {
    Start-Job { 
    Param($0IndexA, $1IndexA, $ParallelNumber)
        For ($c = 0; $c -le (Get-Variable "$($ParallelNumber)IndexA").value.count; $c++){
            (Get-Variable -Name "$($ParallelNumber)IndexA").value[$c]
        }
    } -ArgumentList $0IndexA,$1IndexA, $_
} 

Wait-Job $parJobs | Receive-Job