iT邦幫忙

2024 iThome 鐵人賽

DAY 19
0

*今天對應 **30天挑戰精通 PowerShell *的 Chapter 16

當開始要將 PowerShell 寫成 script 檔,有時在 script 內會需要將執行結果存成變數後再進行處理,而這章節解釋變數後,在之後幾天的章節會開始更頻繁的使用它,在使用它之前,讓我們開始透過書中章節介紹變數及其實用的使用方式。


介紹變數

關於變數( variable ),一個簡單的思考方式是把它想像成電腦記憶體中一個有名稱的盒子。你可以把任何你想要的內容放進這個盒子裡面。你只要使用它的名稱就可以存取這個盒子,而在存取它時,你可以把內容放進去,或是從中取出內容。這些內容會留在盒子裡面,讓你可以一次又一次地取用它們。
Reference - P.255

PowerShell 變數的命名規則

1. 變數名稱以 $ 開頭

所有變數名稱都必須以美元符號 $ 開頭,後面跟隨自定義名稱。

2. 變數名稱不區分大小寫

PowerShell 中的變數名稱不區分大小寫

3. 變數名稱允許字母、數字、底線和短橫

變數名稱可以包含字母、數字、底線 (\_) 和短橫 (-),但名稱中不能以數字開頭,否則會導致語法錯誤。

4. 變數名稱不能以數字開頭

變數名稱必須以字母或底線開頭,不能以數字作為開頭。

5. 變數名稱中的特殊符號使用花括號 {}

如果變數名稱中包含特殊符號(如空格或其他符號),可以用花括號 {} 包裹變數名稱來處理。
舉例:Write-Host ${special variable}

6. 避免使用 PowerShell 保留字

不應使用 PowerShell 的保留字或關鍵字來作為變數名稱,例如 ifelsefunction 等,儘管技術上可以使用 {} 包裝這些保留字作為變數名稱,但不建議這樣做,容易導致程式碼難以維護和閱讀。


把資料儲存進變數

要將資料存入變數,可以使用等號 = 進行賦值。以下是一些範例:

# 儲存文字
$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)"

https://ithelp.ithome.com.tw/upload/images/20241003/20168708ofhLbcTh7K.png
透過這樣的對比,我們先來說說這個例子裡的兩個重點:

跳脫字元 - `

當用 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

處理變數中的單一物件

透過 Index 取用

在 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

ForEach-Object 是 PowerShell 用來對每個物件進行操作的 cmdlet,它會遍歷陣列中的每個元素,並對每個元素執行特定操作。

PS /Users/kanglin/code/30days> $fruits = @("蘋果", "香蕉", "橘子")
PS /Users/kanglin/code/30days> $fruits | ForEach-Object {
>>     Write-Host "水果名稱:$_"
>> }
水果名稱:蘋果
水果名稱:香蕉
水果名稱:橘子

使用 Select-Object

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


上一篇
Day 18 - CIM vs. WMI
下一篇
Day 20 - 互動指令碼的原理:Read-Host、Write-Host、Write-Output
系列文
《30天挑戰精通 PowerShell:從 Windows Server 到 Azure DevOps 自動化之旅》30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言