当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] 如何使用 PowerShell 变量

作者:精品下载站 日期:2024-12-14 03:45:18 浏览:14 分类:玩电脑

如何使用 PowerShell 变量


PowerShell 中的变量用于存储值、数据或稍后在脚本中需要的其他信息。它们还可以用于捕获 cmdlet 的结果。但是,如何创建变量并在函数外部使用它们呢?

在 PowerShell 中,我们有不同的变量所属范围。作用域可以保护变量不被更改,但它们也可以阻止您访问在函数中创建的变量。

在本文中,我们将了解如何分配和使用变量以及如何在不同的范围内使用它们。

PowerShell 变量

在了解所有细节之前,我们先从 PowerShell 变量的基础知识开始。要在 PowerShell 中创建变量,我们将使用美元符号 $。变量名称不区分大小写,通常以驼峰式命名(除了第一个单词外,每个单词的首字母大写)。

$newVariable = "LazyAdmin"

[玩转系统] 如何使用 PowerShell 变量

变量名称可以包含空格和特殊字符,但您确实应该避免这样做。空格和特殊字符会使代码更难阅读,并会导致脚本中出现大量错误输入。

另外值得一提的是,您不必指定变量的类型。 PowerShell 变量是松散类型的,这意味着字符串变量可以更改为整数、数组或哈希表等。

$newVariable = "LazyAdmin"                  # String - System.String
$newVariable = 123                          # Integer - System.Int32 
$newVariable = "Apple", "Grapes", "Kiwi"    # Array - Array of System.String

您还需要知道的是,PowerShell 中存在三种类型的变量。这里我们不是讨论变量是字符串还是整数,而是讨论变量来自哪里。

  • 用户创建的变量 - 这些是上面示例中所示的变量,由您创建和维护的变量。用户创建的变量仅存在于当前 PowerShell 会话中。一旦您关闭 PowerShell 窗口,该变量及其值就会消失。

    但有一个例外,在 PowerShell 配置文件中创建的变量会被保存并可以在不同的 PowerShell 会话中使用。
  • 自动变量 - 自动变量由 PowerShell 创建和维护并存储状态信息。例如,$error$home$profile 是 PowerShell 中的一些自动变量。您可以在此处找到完整列表。
  • 首选项变量 - 这些变量也是由 PowerShell 创建的,但不同之处在于您可以更改这些变量来自定义 PowerShell 的行为。一个很好的例子是变量 $ErrorActionPreference,它允许您设置 PowerShell 在遇到错误时应执行的操作。您可以在这里找到所有偏好变量。

创建和设置变量

正如一开始已经简要介绍的那样,创建变量非常简单。对于简单的松散类型变量,您只需指定变量名称。

$newVariable = $null

也可以在 PowerShell 中创建变量而不指定任何值,甚至不指定 $null。为此,您必须使用 cmdlet Set-Variable,它会为您创建值为 $null 的变量。

Set-Variable -Name $null

set-variable cmdlet 在创建变量时具有一些优势,例如,您可以为变量提供描述或使其在线读取。但一般情况下使用不多。

创建变量时,您不必在 PowerShell 中指定它是字符串还是整数,这非常方便。但是,当创建需要整数的函数时,最好显式指定变量是整数。

要在创建变量时指定类型,您需要使用强制转换表示法。您可以通过将类型名称放在变量前面的括号中来完成此操作:

[string]$stringVariable = "Hello"       # Can only contain a string
[int]$numberVariable = 15               # Can only contain a integer
[datetime]$dateVar = "01/15/24"         # Accepts only datatime objects

正如您在最后一个示例(日期时间变量)中看到的,我们不必设置日期时间对象。 PowerShell 将接受该值,只要它可以将其转换为正确的类型。

以整型变量为例,它不接受带有单词的字符串,但接受字符串中的数字,因为它可以将其转换为整数。

[int]$numberVariable = 15
$numberVariable = "LazyAdmin"

# Error result
Cannot convert value "LazyAdmin" to type "System.Int32". Error: "Input string was not in a correct format."
At line:1 char:1

# This does work however:
$numberVariable = "55"

[玩转系统] 如何使用 PowerShell 变量

PowerShell 变量类型

如果您想知道 PowerShell 中变量的类型,则需要使用 GetType() 方法。这将返回基本类型、类型名称以及有关该变量的许多其他信息。要仅查看类型名称,请选择名称属性:

$numberVariable.GetType().name

# Result
Int32

清除 PowerShell 变量

要清除 PowerShell 中的变量,您有两种选择:使用 Clear-Variable cmdlet 或仅使用 $null 值覆盖变量。 cmdlet 的作用完全相同,因此最方便的方法是像这样分配 $null 值。

$newVariable = $null

# Alternative
Clear-Variable -Name newVariable

删除变量

另一种选择是删除 PowerShell 中的变量。这将从 PowerShell 会话中完全删除该变量及其值。为此,您需要使用 Remove-Variable cmdlet。

当您出于安全原因想要删除或清除 PowerShell 中的变量时,需要记住一些事情。 PowerShell 构建于 .Net 之上,.Net 使用垃圾收集器来清除不再需要的内存项。

但在垃圾收集器通过之前,变量的值仍然在计算机内存中可用。 Clear-Variable cmdlet 实际上会创建变量的副本并将旧变量标记为要收集。而Remove-Variable cmdlet 则标记要收集的原始变量。

因此,如果您需要从内存中删除安全字符串、密码或其他敏感信息,那么最好在将变量更改为 $null 后直接使用 .Net 垃圾收集器。

$newVariable = $null
[System.GC]::Collect() # Call .Net Garbage Collector

打印变量

要在 PowerShell 中打印变量,您只需在控制台中键入变量名称(带有 $ 符号)即可输出值。在脚本中,您通常会使用 Write-Host cmdlet 来输出变量的值。

$numberVariable = "LazyAdmin"

# Directly in a console
$numberVariable

# In a script
Write-Host  $numberVariable

[玩转系统] 如何使用 PowerShell 变量

当您想要将变量包含在字符串中时,您需要确保使用双引号 " "。只有这样,变量的值才会被使用。如果使用单引号,则变量名将用作表达式。

$numberVariable = "LazyAdmin"
Write-Host  "You are reading $numberVariable"

# Result
You are reading LazyAdmin

Write-Host 'The variable $numberVariable contains a string'

# Result
The variable $numberVariable contains a string

如果变量包含对象,则可以使用 . 表示法输出不同的属性。您可以指定变量名称,后跟一个点和属性名称。采用以下哈希表:

$currentDC = [PSCustomObject]@{
    "HostName" = "DC1"
    "OS" = "Windows Server 2019"
    "OS Version" = "10.0.17763"
    "IP Address" = "192.168.1.1"
}

要打印 $currentDC 变量的 HostName ,我们可以编写:

Write-Host $currentDC.Hostname

但是,当您想在字符串中使用相同的属性时,您需要将其括在括号内,如下所示:

Write-Host "The hostname is $($currentDC.Hostname)"

变量范围

在 PowerShell 中,变量可以在三个范围内运行:

  • 全局 - 这在您当前的 PowerShell 会话中有效。包含自动变量和首选项变量。此外,您的 PowerShell 配置文件中定义的变量也存储在此处。
  • 脚本 - 这是在脚本文件运行时创建的。脚本中的命令在脚本范围内运行。
  • 本地 - 当前作用域,可以是全局、脚本或函数内的作用域。

变量仅在其当前作用域及其子作用域中可见和可访问。全局范围内的变量始终可以在脚本或本地范围内访问。

例如,当您在函数内部声明变量时,您无法在该函数外部访问它:

function Get-AuthToken {
    [CmdletBinding()]
    param (
        [string] $TenantId
    )
    # Some code to get a token
    $token = Get-MSCloudIdAccessToken -TenantId $TenantId 
}

Get-AuthToken

# The variable $token would be $null in this case
Get-MSCloudData -Token $token -User 'Test'

要访问或更新另一个作用域内的变量,您需要使用作用域修饰符来访问它。因此,对于上面的示例,我们可以将 $token 变量存储在全局范围内。这样我们也可以在其他函数中使用 $token

# Define the global variable
$global:token = $null

function Get-AuthToken {
    [CmdletBinding()]
    param (
        [string] $TenantId
    )
    # Some code to get a token
    $global:token = Get-MSCloudIdAccessToken -TenantId $TenantId 
}

# Run the function
Get-AuthToken

# $global:token will now contain the token that we need
Get-MSCloudData -Token $global:token -User 'Test'

另一种常见情况是您需要访问 ForEach-Object 循环外部或 Invoke-Command 脚本块外部的变量。在这些情况下,您可以借助 $using: 修饰符访问父变量。在下面的示例中,我们可以使用 $using:services 访问 Scriptblock 内的服务

$services = @(
        'EventSystem',
        'w32time', 
        'netlogon'
        )

    $stoppedServices = Invoke-Command -Computername $computername -ScriptBlock {Get-Service -Name $using:services | where {$_.Status -eq 'Stopped'}}

尝试尽可能减少全局作用域的使用,因为这将使您的代码更难以阅读,并且可以从脚本中的任何位置访问它。如果您在 PowerShell 中使用全局变量,请在脚本开头声明它们。

列出变量

您忘记了变量名称吗?或者想知道您当前使用了哪些变量?您可以使用 Get-Variable cmdlet 查看会话中的所有变量。这将列出所有全局和局部变量及其会话。

如果运行不带任何参数的 cmdlet,它将返回所有变量。为了帮助您查找变量,Get-Variables cmdlet 附带了几个参数。例如,我们创建了一个包含单词 number 的变量,但不知道确切的名称。

要查找变量名称,您可以使用 -name 参数和 * 作为通配符:

Get-Variable -name *number*

# Result
Name                           Value
----                           -----
numberVariable                 LazyAdmin

您还可以使用 -Include-Exclude 参数仅选择带有(或不带有)特定字符串的变量。如果您只想查看变量的值,请使用 -ValueOnly 参数。

总结

变量是每种编程或脚本语言(包括 PowerShell)的基础。它们允许您存储信息并稍后在脚本中使用它。保持变量名称始终清晰且有意义。

全局变量有其用处,但要尽量减少使用。它们将使阅读代码和调试变得更加困难。

我希望这篇文章对您有所帮助,如果您有任何疑问,请在下面发表评论。

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯