*今天對應 **30天挑戰精通 PowerShell *的 Chapter 16
當開始要將 PowerShell 寫成 script 檔,有時在 script 內會需要將執行結果存成變數後再進行處理,而這章節解釋變數後,在之後幾天的章節會開始更頻繁的使用它,在使用它之前,讓我們開始透過書中章節介紹變數及其實用的使用方式。
關於變數( variable ),一個簡單的思考方式是把它想像成電腦記憶體中一個有名稱的盒子。你可以把任何你想要的內容放進這個盒子裡面。你只要使用它的名稱就可以存取這個盒子,而在存取它時,你可以把內容放進去,或是從中取出內容。這些內容會留在盒子裡面,讓你可以一次又一次地取用它們。
Reference - P.255
$
開頭所有變數名稱都必須以美元符號 $
開頭,後面跟隨自定義名稱。
PowerShell 中的變數名稱不區分大小寫
變數名稱可以包含字母、數字、底線 (\_
) 和短橫 (-
),但名稱中不能以數字開頭,否則會導致語法錯誤。
變數名稱必須以字母或底線開頭,不能以數字作為開頭。
{}
如果變數名稱中包含特殊符號(如空格或其他符號),可以用花括號 {}
包裹變數名稱來處理。
舉例:Write-Host ${special variable}
不應使用 PowerShell 的保留字或關鍵字來作為變數名稱,例如 if
、else
、function
等,儘管技術上可以使用 {}
包裝這些保留字作為變數名稱,但不建議這樣做,容易導致程式碼難以維護和閱讀。
要將資料存入變數,可以使用等號 =
進行賦值。以下是一些範例:
# 儲存文字
$message = "歡迎使用 PowerShell"
# 儲存數字
$count = 10
# 儲存計算結果
$sum = 5 + 5
透過 GetType() 的方法將目前變數的類型名稱顯示出來,另外整理出透過 Write-Host 一次性的將變數名稱、變數值及變數類型打印出來。
Write-Host "`$message 的值為 $message, `$message 的類型為 $message.GetType().Name"
Write-Host "`$message 的值為 $message, `$message 的類型為 $($message.GetType().Name)"
透過這樣的對比,我們先來說說這個例子裡的兩個重點:
當用 Write-Host 要 Print 出 $ 字號時,我們需要透過跳脫字元將 $ 字號跳脫,使 PowerShell 能夠將其視為一般 String 呈現出來而不是呈現出該變數所存放的值。
$()
當在雙引號 "" 內使用子運算式時,會將括號內的表達式執行並將結果插入到字串中,其具體邏輯為:
$(…) 會先執行括號內的 PowerShell 代碼,無論裡面是變數、函數還是方法,然後將結果作為字串的一部分。
在這個例子中,$message.GetType().Name 這個表達式會取得 $message 變數的型別,並返回 String。
在 PowerShell 中,雙引號 "
和單引號 '
的使用方式有所不同。雙引號內的變數會被解析,而單引號內的變數則會被視為純文字( 字面字串 literal string )。
$name = "小明"
# 使用雙引號,變數會被替換為其值
Write-Host "你好,$name" # 輸出:你好,小明
# 使用單引號,變數名稱會被原樣顯示
Write-Host '你好,$name' # 輸出:你好,$name
這次的範例除了剛剛所提到了跳脫字元外,加上了跳脫字元加上特定字母會被 PowerShell 視為擁有特定用途的符號,一般情況下,n 只是一般字母,但是在它的前面加上跳脫字元後,它就變成了擁有換行目的的符號。
PS /Users/kanglin/code/30days> $computername = "macAir1"
PS /Users/kanglin/code/30days> $phrase = "`$computername`ncontains`n$computername"
PS /Users/kanglin/code/30days> $phrase
$computername
contains
macAir1
實際上我們在這裡要討論的是:Array(陣列),我們可以透過兩種方式將 Array 賦值給變數
# Method 1 - 透過 , 建立一個包含多個數字的陣列
$numbers = 1, 2, 3, 4, 5
# Method 2 - 使用 @() 語法
$fruits = @("蘋果", "香蕉", "橘子")
看一下用這兩種方式建立的變數其值的類型
PS /Users/kanglin/code/30days> $fruits.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
PS /Users/kanglin/code/30days> $numbers.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
那這樣,這兩種方法到底差在哪裡?
Method 1 - 使用逗號 ,
建立的陣列在 PowerShell 中被稱為「簡單陣列」,它自動將每個元素當作單一物件的一部分。如果只有一個元素,PowerShell 不會將其視為陣列,而是會將它當作單一物件處理。
PS /Users/kanglin/code/30days> $numbers = 1, 2, 3, 4, 5
PS /Users/kanglin/code/30days> $singleNumber = 5
PS /Users/kanglin/code/30days> $numbers.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
PS /Users/kanglin/code/30days> $singleNumber.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Int32 System.ValueType
Method 2 - 使用 @()
明確建立陣列,因此即使只有一個元素,它也會將其視為陣列。
PS /Users/kanglin/code/30days> $singleElementArray = @("蘋果")
PS /Users/kanglin/code/30days> $singleElementArray.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
在 PowerShell 中,陣列的索引( index )也是從 0 開始,當要取用陣列裡的單一物件時,可以透過變數搭配中括弧 [index]
指定,也可以使用 -
來從最後一個物件開始取用(不過就要從 -1
開始,不是從 -0
)。
PS /Users/kanglin/code/30days> $fruits = @("蘋果", "香蕉", "橘子")
PS /Users/kanglin/code/30days> $fruits[0]
蘋果
PS /Users/kanglin/code/30days> $fruits[1]
香蕉
PS /Users/kanglin/code/30days> $fruits[2]
橘子
PS /Users/kanglin/code/30days> $fruits[-1]
橘子
PS /Users/kanglin/code/30days> $fruits[-2]
香蕉
PS /Users/kanglin/code/30days> $fruits[-3]
蘋果
透過變數裡的屬性 count
去確認其物件數量。
PS /Users/kanglin/code/30days> $fruits = @("蘋果", "香蕉", "橘子")
PS /Users/kanglin/code/30days> $fruits.count
3
透過 index 指定目標物件後,重新賦值即可。
PS /Users/kanglin/code/30days> $fruits = @("蘋果", "香蕉", "橘子")
PS /Users/kanglin/code/30days> $fruits[0] = "榴蓮"
PS /Users/kanglin/code/30days> $fruits
榴蓮
香蕉
橘子
透過索引或迴圈來存取每個元素:
PS /Users/kanglin/code/30days> $fruits = @("蘋果", "香蕉", "橘子")
PS /Users/kanglin/code/30days> Write-Host $fruits[0] # 透過 index
蘋果
PS /Users/kanglin/code/30days> foreach ($fruit in $fruits) {
>> Write-Host "水果:$fruit"
>> } # 透過迴圈
水果:蘋果
水果:香蕉
水果:橘子
ForEach-Object 是 PowerShell 用來對每個物件進行操作的 cmdlet,它會遍歷陣列中的每個元素,並對每個元素執行特定操作。
PS /Users/kanglin/code/30days> $fruits = @("蘋果", "香蕉", "橘子")
PS /Users/kanglin/code/30days> $fruits | ForEach-Object {
>> Write-Host "水果名稱:$_"
>> }
水果名稱:蘋果
水果名稱:香蕉
水果名稱:橘子
Select-Object 是用來從物件中選擇特定屬性或篩選部分元素的 cmdlet。通常用來從物件中提取資料,或限制顯示的結果。
PS /Users/kanglin/code/30days> $fruits = @("蘋果", "香蕉", "橘子")
PS /Users/kanglin/code/30days> $selectedFruits = $fruits | Select-Object -First 2
PS /Users/kanglin/code/30days> Write-Host "選擇的水果有:$selectedFruits"
選擇的水果有:蘋果 香蕉
雖然 PowerShell 是動態型別語言(指在程式執行期間才會決定變數的資料類型的編程語言),但我們可以明確指定變數的資料類型,以確保資料的正確性。
# 指定為整數類型
[int]$age = 30
# 指定為字串類型
[string]$name = "小華"
# 指定為布林值
[bool]$isActive = $true
Day 20 - 互動指令碼的原理:Read-Host、Write-Host、Write-Output