Windows PowerShell 講座(4)—變數

發佈日期: 2008 年 2 月 19 日

**作者:**賴榮樞
    www.goodman-lai.idv.tw

如同一般的程式語言,Windows PowerShell 也提供了數種存放資料的方式,而變數是其中基本且常用的方式。本文將說明 Windows PowerShell 所提供的變數功能,包括變數的型別、轉換、宣告、內建變數,以及處理變數的 cmdlet。

本頁內容

變數名稱
變數型別
型別轉換
資料型別
宣告變數型別
變數都是物件
內建變數
處理變數的 cmdlet
總結

變數是預留給程式存放資料的記憶體空間,現代的高階程式語言都能自行處理記憶體空間配置的細節,不需開發者介入,開發者只需要瞭解 Windows PowerShell 變數的特性,即可直接使用變數(雖然 Windows PowerShell 提供了 New-Variable cmdlet 來宣告並指定變數初值,但未事先宣告亦可使用變數)。

說明變數之前,還記得我們在上一篇文章《Windows PowerShell 講座(3)—PS磁碟機》提過專門用來存放變數的 PS 磁碟機 variable:,以下的指令可以列出目前 Windows PowerShell 環境裡的「所有」變數例子(就算您尚未宣告或自訂任何變數,一執行 Windows PowerShell 之後,就有許多內建的變數):

dir variable:

變數名稱

Windows PowerShell 規定變數名稱的第一個字元必須是$符號,而其他的字元可以混合英文字母、中文字元、數字和底線符號;雖然變數名稱也可以使用底線以外的任何符號,但就必須以大括號抓住變數名稱。Windows PowerShell 還有許多內建變數(本文後續將會說明),因此您的變數名稱最好不要與這些內建變數重複;此外,變數名稱是不分大小寫,因此以下前三個變數實際上是同一個變數:

$CompanyName
$companyName
$companyname

# 只要以大括號括住,
# Windows PowerShell的變數名稱可以使用任何字元
${My Variable Name--@@--}

變數型別

Windows PowerShell 的變數除了可以用在指令碼程式,也可以用在文字操作模式。Windows PowerShell 的變數在未指定變數值之前,都是 Variant 的物件型別,但是指定了型別或變數值之後,變數的子型別就會有所改變。例如在 Windows PowerShell 文字操作模式輸入:

$a="3"
$b="4"
$a+$b
			

最後會顯示 34,是因為我們指定給這兩個變數的值,都以雙引號括住 (也可以用單引號括住),這等於是將這兩個變數指定成字串型別,而加號對字串型別的資料是連接運算子,因此運算結果會是 34。使用 Windows PowerShell 的變數不需特意指定型別,當我們將變數值指定給變數時,Windows PowerShell 會自動依照變數值的型別,賦予變數型別。再舉一例,如果上述改成以下,結果就會是7,因為以下兩個變數值是整數,因此加號會進行加法運算:

$a=3
$b=4
$a+$b
			

型別轉換

如果以加號處理字串和整數型別的變數,結果會是如何呢?嗯,這要看加數的型別是字串還是整數。例如以下三個例子的結果大不相同,我們先假設有以下幾個變數:

$a="3"
$b=4
$c="SS"
			
  • $a + $b:是字串加整數,而且 Windows PowerShell 可以將 4 轉換成字串型別,因此會對兩個變數進行字串連接而得到 34。

  • $b + $a:是整數加字串,而且 Windows PowerShell 可以將 "3" 轉換成整數型別,因此會對兩個變數進行算術相加而得到7。

  • $b + $c:也是整數加字串,但是 Windows PowerShell 無法將 "SS" 轉換成整數型別,因此會出現格式錯誤的訊息。

  • $c + $b:雖然也是字串加整數,但與上例不同的是,Windows PowerShell 可以將 4 轉換成字串型別,因此會對兩個變數進行字串連接而得到 SS4。

變數型別的轉換除了交給 Windows PowerShell 自動處理,您也可以自行指定轉換的型別,例如:

  • [int]$a + $b:由於在 $a 之前加了 [int],等於是在運算時強制將字串 "3" 轉換成整數 3,因此會對兩個變數進行算術相加而得到 7。

  • [string]$b + $a:在$b之前加了 [string],等於是在運算時強制將整數4轉換成字串 "4",因此會對兩個變數進行字串連接而得到 43。

  • [string]$b + $c:在 $b 之前加了 [string],等於是在運算時強制將整數 4 轉換成字串 "4",因此會對兩個變數進行字串連接而得到 4SS。請注意,就算在 $c 之前加上 [int],還是無法強制將字串SS轉換成整數 SS,因此還是會出現格式錯誤的訊息。

由於 Windows PowerShell 的變數也都是物件,擁有許多方法可供叫用,而如果想要知道變數的型別,可以利用其中的 GetType 方法取得變數的型別資訊,或者再加上 Name 屬性,即可直接列出型別名稱。例如:

$a.GetType()
$b.GetType().Name
			

資料型別

Windows PowerShell 的資料型別相當多樣,因為 Windows PowerShell 的基底是 .NET Framework,因此兩者的資料型別是相通的,但為了方便表示,Windows PowerShell 已經將常用的資料型別名稱另外設定了別名,例如 int 或 int32 是 System.Int32、double 是System.Doule、string 是 System.String 的別名。以下列出的是常用的資料型別:

[adsi]

AD 服務物件

[array]

陣列

[bool]

布林值 (True 或 False)

[byte]

8 位元無號整數

[char]

單一個 Unicode 字元(16位元)

[datetime]

日期或時間

[decimal]

128 位元十進位值

[double]

倍精度 64 位元浮點數

[hashtable]

雜湊表物件

[int] 或 [int32]

32 位元有號整數

[long]

64 位元有號整數

[regex]

規則運算式

[single]

單精度 32 位元浮點數

[scriptblock]

程式區塊

[string]

固定長度的 Unicode 字串

[WMI]

WMI 執行個體或集合

[WMIclass]

WMI 類別

[xml]

Xml 物件

宣告變數型別

之前變數的例子都未指定型別,因此 Windows PowerShell 會依據變數值的型別,自動轉換變數型別,而且會動態改變型別;例如以下的例子:

Dd125499.66-winPowerShell-4-01(zh-tw,TechNet.10).jpg

這個例子分別將整數、字串、小數等三種型別的值指定給變數 $Age,並且在指定之後利用 $Age.GetType().Name 檢視此變數的型別,您會發現變數型別也的確隨著變數值動態變成 Int32、String、Double。

不過這種看似方便的功能,實際上可能因為使用的疏忽而出現與預期不符的型別,以及不易察覺的錯誤結果。因此,越大、越複雜的程式,建議應該要自行宣告變數型別,以免因為 Windows PowerShell 自動轉換型別而造成預期之外的結果。

若要宣告變數型別,可以如下方式指定其型別及初值,例如以下的例子會將變數 $Age 的型別宣告成整數 [int],並且設定初值為 18:

[int]$Age=18

這時如果再將 19、"Cathy"、"20" 指定給變數 $Age,會有什麼樣的結果呢?如下圖。

Dd125499.66-winPowerShell-4-02(zh-tw,TechNet.10).jpg

將數值 19 指定給變數 $Age 的結果一如我們的預期,變數值因而變成 19,變數型別依然是 Int32。然而將字串 "Cathy" 指定給變數卻出現了格式不正確的錯誤訊息,這正是因為我們已經先將變數 $Age 宣告成 Int32 型別所致。最後又將字串 "20" 指定給變數 $Age,但結果是否出乎您意料?不僅沒有出現錯誤訊息,而且經由檢查發現變數 $Age 的型別依然是 Int32,但是變數值變成 20 了。

再如以下的例子:

Dd125499.66-winPowerShell-4-03(zh-tw,TechNet.10).jpg

我們先宣告了字串型別的變數 $var,但將其初值指定為整數值 77,檢查其變數型別是為 String。隨後再分別將浮點數和 DateTime 型別資料指定給變數 $var,並檢查變數 $var 的型別,可以發現資料指定給變數時,若資料與變數的型別不符,Windows PowerShell 會「盡量」將資料型別自動轉換成變數的型別。

變數都是物件

變數都是物件,是 Windows PowerShell 最大的特點。例如本文之前曾經利用以下的方式找出變數的型別,就是叫用變數(這種物件)的 GetType 方法,這個方法會傳回變數的 Type 物件,而 Type 物件的 Name 屬性值則是型別名稱:

[int]$Age=18
$Age.GetType()
$Age GetType().Name
			

變數就是物件,讓變數的處理添加了許多彈性與便利,除了上述以 GetType 方法得知變數型別之外,每種型別的變數還有許多不同的方法和屬性。我們可以利用 Get-Member 得知變數擁有的方法和屬性,例如以下的指令可以顯示上述字串變數 $Company 和整數變數 $Age 的方法和屬性;以下兩個圖分別是執行結果:

$Age | Get-Member
$Company | Get-Member
			

Dd125499.66-winPowerShell-4-04(zh-tw,TechNet.10).jpg

Dd125499.66-winPowerShell-4-05(zh-tw,TechNet.10).jpg

從以上兩個圖可以發現,整數和字串型別的變數物件,各有共同和不同的方法、屬性,例如之前示範過的 GetType 是兩者共同的方法,而整數變數物件的 ToString 方法可以將整數值轉換成字串、字串變數物件的 Length 屬性值是該字串的長度(這些方法或屬性的詳細用法,可以從 .NET Framework 的說明檔查到);例如以下的例子會將字串變數 $Company 的長度指定到整數變數 $CmpyLen:

[int]$CmpyLen=$Company.Length

內建變數

管理者除了可以自訂變數來用,Windows PowerShell 還提供了許多內建的變數,這類的變數分成自動變數和環境變數兩類,儲存著系統或 Windows PowerShell 環境的相關資訊。以下兩個表格列出了這兩類變數及簡述。

自動變數

$$

內含 Windows PowerShell 最後一次接收到的內容的最後一個指令(也就是您最後一次輸入到 Windows PowerShell 並按下 Enter 按鍵的內容的最後一個指令)。

$?

如果最後一次的指令操作是成功的,其值是 True,否則是 False。

$^

內含 Windows PowerShell 最後一次接收到的內容的第一個指令(也就是您最後一次輸入到 Windows PowerShell 並按下 Enter 按鍵的內容的第一個指令)。

$_

內含目前用在指令碼區塊、過濾器、陳述式裡的管線物件。

$Args

內含傳給函式的參數陣列。

$ConfirmPreference

指定 Windows PowerShell 完成有副作用的動作之前要先作什麼。

$ConsoleFileName

目前主控台檔案的名稱。

$DebugPreference

指定在指令碼程式裡以 Write-Debug 寫入資料,或在 cmdlet 或提供者以 WriteDebug 寫入資料的動作。

$Error

指定執行 cmdlet 但發生錯誤的相關資訊,為物件型別。

$ErrorActionPreference

指定在指令碼程式裡以 Write-Error 寫入資料,或在 cmdlet 或提供者以 WriteError 寫入資料的動作。

$ErrorView

指定顯示錯誤的模式。

$ExecutionContext

指定可用於 cmdlet 的執行物件。

$False

布林值 False。

$FormatEnumerationLimit

指定 IEnumerable 物件列舉值的界限。

$foreach

foreach 迴圈的列舉值。

$Home

使用者的家資料夾 (home directory),相當於 %homedrive%%homepath%。

$Host

內含目前 Windows PowerShell 的資訊。

$Input

用在管線中間的指令碼區塊。

$LASTEXITCODE

內含最後一個 Win32 執行檔直行結果的結束碼。

$MaximumAliasCount

內含目前這個 Windows PowerShell 階段最大可用的別名數量。

$MaximumDriveCount

內含最大可用的磁碟數量 (但不含底層作業系統所提供)。

$MaximumErrorCount

內含最大可用的錯誤數量。

$MaximumFunctionCount

內含目前這個 Windows PowerShell 階段最大可用的函式數量。

$MaximumHistoryCount

內含命令歷程項目的最大數量。

$MaximumVariableCount

內含目前這個 Windows PowerShell 階段最大可用的變數數量。

$MaximumAliasCount

內含目前這個 Windows PowerShell 階段最大可用的別名數量。

$MyInvocation

包含指令碼如何叫用的資訊。

$NestedPromptLevel

Windows PowerShell 提示的巢狀階層,最外層為 0。

$null

NULL 值。

$OFS

用在陣列轉換成字串的輸出欄位分隔器,預設是空白字元。

$PID

Windows PowerShellprocess.$pi 的行程 ID 值。

$Profile

使用者設定檔 (profile.ps1) 的位置。

$ProgressPreference

指定 progress 記錄送出後的動作

$PsHome

安裝 Windows PowerShell 的資料夾名稱。

$PWD

目前工作資料夾。

$ReportErrorShowExceptionClass

若設為 True,當顯示類別名稱時,會輸出例外的類別名稱。預設值是 False。

$ReportErrorShowInnerException

若設為 True,會輸出內部例外的完整串鏈,每個例外訊息會縮排成額外的階層,並且由此列出的剩餘選項所格式化。預設值為 False。

$ReportErrorShowSource

若設為 True,會顯示例外來源的組件名稱。預設值為 True。

$ReportErrorShowStackTrace

若設為 True,會輸出例外的堆疊追蹤。預設值為 False。

$ShellId

Windows PowerShell 殼層執行的名稱 (預設是 Microsoft.PowerShell)。

$ShouldProcessPreference

指定 ShouldProcess 用在 cmdlet 的動作。

$ShouldProcessReturnPreference

ShouldPolicy 的傳回值。

$StackTrace

內含最後一次錯誤的詳細堆疊追蹤資訊。

$True

布林值 True。

$VerbosePreference

指定在指令碼程式裡以 Write-Verbose 寫入資料,或在 cmdlet 或提供者以 WriteVerbose 寫入資料的動作。

$WarningPreference

指定在指令碼程式裡以 Write-Warning 寫入資料,或在 cmdlet 或提供者以 WriteWarning 寫入資料的動作。

$WhatIfPreference

指定 -whatif 是否要對所有的命令有作用。

環境變數

我們在上一篇文章《Windows PowerShell 講座(3)—PS磁碟機》提過專門用來放置環境變數的 PS 磁碟機 env:,;例如以下的例子:

# dir 是 Get-Childitem 的別名
# 顯示所有環境變數名稱及值
dir env:
# 顯示 Path 環境變數及值
dir env:path
# 顯示 SystemRoot 環境變數及值
dir env:systemroot
				

Dd125499.66-winPowerShell-4-06(zh-tw,TechNet.10).jpg

如果想要個別使用 Windows PowerShell 所提供的環境變數,可以利用下列的語法:

$env:<環境變數名稱>;
				

例如以下的例子:

# 使用 Path 環境變數
$env:path
				

FakePre-ee37efeec99649b39ebf434e5b9a9e54-2764c235d2584b3cb6da9922cf4e5b45

環境變數值也可以利用下列語法更改:

$env:<環境變數名稱>;
= <變數值>;
				

例如以下兩個例子都是在現有的 Path 環境變數值加上 c:\MyMSH:

$env:path = $env:path + ";c:\MyMSH"
set-item -path env:path -value ($env:path + ";c:\MyMSH ")
				

處理變數的 cmdlet

為了方便變數的處理,Windows PowerShell 也提供了一組 cmdlet,以下本文將討論這些 cmdlet 的用法,但要先請留意的是,這些 cmdlet 裡的變數名稱都不需要加上 $ 符號。

建立變數:New-Variable

New-Variable (別名為 nv) 都可以用來建立變數,如果欲建立的變數已存在,會產生錯誤。例如以下的例子:

# 建立變數 rtYu,但未指定值
nv rtYu

# 建立變數 Age,其值為整數 18
nv age -value 18

# 建立變數 Company,其值為字串 Microsoft
nv Company -value "Microsoft"
				

指定變數值:Set-Variable

Set-Variable (別名為 set) 可以用來指定變數值,如果欲指定值的變數不存在,會自動建立該變數。例如以下的例子:

# 建立變數 Company,其值為字串 Microsoft
set Company -value "Microsoft"
				

取得變數:Get-Variable

Get-Variable (別名是 gv) 可以用來取得已經建立的變數,例如以下的例子取得上例建立的兩個變數:

Dd125499.66-winPowerShell-4-07(zh-tw,TechNet.10).jpg

清除變數值:Clear-Variable

Clear-Variable (別名是 clv) 可以用來清除變數值,例如以下的例子會清除上例建立的兩個變數值:

Dd125499.66-winPowerShell-4-08(zh-tw,TechNet.10).jpg

刪除變數:Remove-Variable

Remove-Variable (別名為 rv) 可以用來刪除變數,例如以下的例子會清除上例建立的兩個變數 (因此以 gv 取回變數會產生找不到變數的錯誤訊息):

Dd125499.66-winPowerShell-4-09(zh-tw,TechNet.10).jpg

總結

以 .NET Framework 為基礎的 Windows PowerShell,所提供的變數功能與 .NET Framework 也有許多相通之處,例如資料型別以及變數即物件等,尤其是後者有助於變數的處理。此外,Windows PowerShell 也提供了一組專門處理變數的 cmdlet,以及為數眾多的內建變數。不過,關於變數的範圍,本文將留待論及函式時,再一併討論。