gpt4 book ai didi

powershell - PowerShell 的 setlocal/endlocal 等效项是什么?

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

目标

将环境变量更改隔离到代码块。

背景

如果我想创建一个批处理脚本来运行需要设置环境变量的命令,我知道我可以这样做:

setlocal
set MYLANG=EN
my-cmd dostuff -o out.csv
endlocal

但是,当我需要使用 shell 脚本语言时,我倾向于使用 PowerShell。我知道如何设置环境变量( $env:TEST="EN"),当然这只是一个简单的例子。但是,我不确定如何达到与批处理脚本相同的效果。令人惊讶的是,我也没有看到任何问题。

我知道使用 $env:TEST="EN" 进行设置是进程范围的,但如果我在单个终端 session 中使用脚本作为小型实用程序,那是不切实际的。

我目前的方法:
  • 进入setlocal .但这不是命令行指令……我希望如此。
  • 将当前变量保存到临时变量,运行我的命令,将其改回......有点傻。
  • 功能级别范围(尽管我怀疑成功,因为 $env: 似乎与 $global: 没有太大区别)

  • 函数范围不胜过对 $env: 的引用
    $env:TEST="EN"
    function tt {
    $env:TEST="GB"
    ($env:TEST)
    }

    ($env:TEST)
    tt
    ($env:TEST)

    输出:
    C:\Users\me> .\eg.ps1
    EN
    GB
    GB

    最佳答案

    批处理文件 , 所有 shell变量也是环境变量 ;因此,setlocal ... endlocal也为环境变量提供了本地范围。
    相比之下,在 电源 , shell 变量(例如 $var )不同于环境变量(例如 $env:PATH ) - 通常是有益的区别。
    鉴于 设置环境变量的最小范围是当前进程 - 因此整个 PowerShell session ,你必须手动管理较小的自定义范围 , 如果你想在进程中执行此操作(这是 setlocal ... endlocalcmd.exe 中所做的,PowerShell 没有内置等效项;对于自定义范围的 shell 变量,请使用 & { $var = ...; ... } ):
    过程中方法:自定义范围的手动管理:
    为了在一定程度上减轻痛苦,您可以使用脚本 block ({ ... })来提供命令的独特视觉分组,当使用 & 调用该命令时还创建一个新的本地范围,以便任何 aux.您在脚本 block 中定义的变量会自动超出范围(您可以用 ; 分隔的命令将其写成一行):

    & { 
    $oldVal, $env:MYLANG = $env:MYLANG, 'EN'
    my-cmd dostuff -o out.csv
    $env:MYLANG = $oldVal
    }
    更简单地说,如果没有预先存在的 MYLANG必须恢复的值:
    & { $env:MYLANG='EN'; my-cmd dostuff -o out.csv; $env:MYLANG=$null }
    $oldVal, $env:MYLANG = $env:MYLANG, 'EN'保存 $env:MYLANG 的旧值(如果有)在 $oldVal同时将值更改为 'EN' ;在 Get-Help about_Assignment_Operators 中解释了这种一次赋值给多个变量的技术(在某些语言中称为解构赋值)。 ,“分配多个变量”部分。
    一个 更合适、更健壮但更冗长的解决方案是使用 try { ... } finally { ... } :
    try {
    # Temporarily set/create $env:MYLANG to 'EN'
    $prevVal = $env:MYLANG; $env:MYLANG = 'EN'

    my-cmd dostuff -o out.csv # run the command(s) that should see $env:MYLANG as 'EN'

    } finally { # remove / restore the temporary value
    # Note: if $env:MYLANG didn't previously exist, $prevVal is $null,
    # and assigning that back to $env:MYLANG *removes* it, as desired.
    $env:MYLANG = $prevVal
    }
    但是请注意,如果您只在临时修改的环境中调用外部程序,则不需要 try。/ catch ,因为从 PowerShell 7.1 开始,外部程序永远不会导致 PowerShell 错误,尽管 may change in the future .
    为了方便这种方法, this answer到相关问题提供 便利功能Invoke-WithEnvironment ,它允许您编写与以下相同的调用:
    # Define env. var. $env:MYLANG only for the duration of executing the commands
    # in { ... }
    Invoke-WithEnvironment @{ MYLANG = 'EN' } { my-cmd dostuff -o out.csv }

    替代方案,使用辅助过程:
    通过使用辅助进程并仅在此处设置 transient 环境变量,
  • 您避免了调用后恢复环境的需要
  • 但是您付出了性能损失,并且增加了调用复杂性。

  • 使用辅助。 cmd.exe流程:
    cmd /c "set `"MYLANG=EN`" & my-cmd dostuff -o out.csv"
    笔记:
  • "..."选择了引用,以便您可以在命令中引用 PowerShell 变量;嵌入式 "然后必须转义为 `"
  • 此外,目标命令的参数必须根据 cmd.exe 传递。的规则(与手头的简单命令没有区别)。

  • 使用辅助。子 PowerShell session :
    # In PowerShell *Core*, use `pwsh` in lieu of `powershell`
    powershell -nop -c { $env:MYLANG = 'EN'; my-cmd dostuff -o out.csv }
    笔记:
  • 启动另一个 PowerShell session 的成本很高。
  • 脚本 block ( { ... } ) 的输出会在调用范围内进行序列化和反序列化;对于字符串输出,没关系,但复杂的对象,如 [System.IO.FileInfo]反序列化为原件的仿真(这可能是也可能不是问题)。
  • 关于powershell - PowerShell 的 setlocal/endlocal 等效项是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48432667/

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