دستوراتی که درون کنسول مینویسیم، تک خطی یا one-linear هستند؛ هر چند میتوان با زدن کلیدهای Shift + Enter دستورات چندخطی هم نوشت یا حتی با گذاشتن semicolon بعد از هر دستور میتوانیم دریک خط چندین دستور را پشتسر هم بنویسیم. اما برای نوشتن دستورات طولانیتر بهتر است دستورات را درون فایلهای جدایی قرار دهیم و از VSCode یا PowerShell ISE (فقط در ویندوز) نیز برای نوشتن اسکریپتها استفاده کرد. اسکریپتهای PowerShell با پسوند ps1 و psm1 (برای نوشتن ماژول) هستند؛ هر چند چندین پسوند دیگر نیز برای فایلهای PowerShell وجود دارند که در اینجا میتوانید لیست آنها را مشاهده کنید. درون یک فایل ps1 امکان نوشتن و ترکیب دستورات مختلف را داریم. همچنین میتوانیم از امکانات زبان سیشارپ هم استفاده کنیم؛ زیرا PowerShell در واقع اپلیکیشنی است که توسط NET Core. و با زبان #C نوشته شدهاست. در نتیجه میتوانیم بگوئیم زبان اسکریپتی که در PowerShell استفاده میشود، یک DSL برای زبان #C است. در PowerShell همه چیز یک آبجکت محسوب میشود. برای تست این مورد میتوانید درون کنسول PowerShell دستور زیر را وارد کنید:
PS> "" | Get-Member
دستور فوق یک لیست از تمامی توابع و پراپرتیهای نوع System.String را نمایش خواهد داد:
TypeName: System.String Name MemberType Definition ---- ---------- ---------- Clone Method System.Object Clone(), System.Object ICloneable.Clone() CompareTo Method int CompareTo(System.Object value), int CompareTo(strin… Contains Method bool Contains(string value), bool Contains(string value… CopyTo Method void CopyTo(int sourceIndex, char[] destination, int de… EndsWith Method bool EndsWith(string value), bool EndsWith(string value… EnumerateRunes Method System.Text.StringRuneEnumerator EnumerateRunes() Equals Method bool Equals(System.Object obj), bool Equals(string valu… GetEnumerator Method System.CharEnumerator GetEnumerator(), System.Collectio… GetHashCode Method int GetHashCode(), int GetHashCode(System.StringCompari… GetPinnableReference Method System.Char&, System.Private.CoreLib, Version=6.0.0.0, … GetType Method type GetType() GetTypeCode Method System.TypeCode GetTypeCode(), System.TypeCode IConvert… IndexOf Method int IndexOf(char value), int IndexOf(char value, int st… IndexOfAny Method int IndexOfAny(char[] anyOf), int IndexOfAny(char[] any… Insert Method string Insert(int startIndex, string value) IsNormalized Method bool IsNormalized(), bool IsNormalized(System.Text.Norm… LastIndexOf Method int LastIndexOf(string value, int startIndex), int Last… LastIndexOfAny Method int LastIndexOfAny(char[] anyOf), int LastIndexOfAny(ch… Normalize Method string Normalize(), string Normalize(System.Text.Normal… PadLeft Method string PadLeft(int totalWidth), string PadLeft(int tota… PadRight Method string PadRight(int totalWidth), string PadRight(int to… Remove Method string Remove(int startIndex, int count), string Remove… Replace Method string Replace(string oldValue, string newValue, bool i… ReplaceLineEndings Method string ReplaceLineEndings(), string ReplaceLineEndings(… Split Method string[] Split(char separator, System.StringSplitOption… StartsWith Method bool StartsWith(string value), bool StartsWith(string v… Substring Method string Substring(int startIndex), string Substring(int … ToBoolean Method bool IConvertible.ToBoolean(System.IFormatProvider prov… ToByte Method byte IConvertible.ToByte(System.IFormatProvider provide… ToChar Method char IConvertible.ToChar(System.IFormatProvider provide… ToCharArray Method char[] ToCharArray(), char[] ToCharArray(int startIndex… ToDateTime Method datetime IConvertible.ToDateTime(System.IFormatProvider… ToDecimal Method decimal IConvertible.ToDecimal(System.IFormatProvider p… ToDouble Method double IConvertible.ToDouble(System.IFormatProvider pro… ToInt16 Method short IConvertible.ToInt16(System.IFormatProvider provi… ToInt32 Method int IConvertible.ToInt32(System.IFormatProvider provide… ToInt64 Method long IConvertible.ToInt64(System.IFormatProvider provid… ToLower Method string ToLower(), string ToLower(cultureinfo culture) ToLowerInvariant Method string ToLowerInvariant() ToSByte Method sbyte IConvertible.ToSByte(System.IFormatProvider provi… ToSingle Method float IConvertible.ToSingle(System.IFormatProvider prov… ToString Method string ToString(), string ToString(System.IFormatProvid… ToType Method System.Object IConvertible.ToType(type conversionType, … ToUInt16 Method ushort IConvertible.ToUInt16(System.IFormatProvider pro… ToUInt32 Method uint IConvertible.ToUInt32(System.IFormatProvider provi… ToUInt64 Method ulong IConvertible.ToUInt64(System.IFormatProvider prov… ToUpper Method string ToUpper(), string ToUpper(cultureinfo culture) ToUpperInvariant Method string ToUpperInvariant() Trim Method string Trim(), string Trim(char trimChar), string Trim(… TrimEnd Method string TrimEnd(), string TrimEnd(char trimChar), string… TrimStart Method string TrimStart(), string TrimStart(char trimChar), st… TryCopyTo Method bool TryCopyTo(System.Span[char] destination) Chars ParameterizedProperty char Chars(int index) {get;} Length Property int Length {get;}
در واقع میتوانیم بگوئیم هرچیزی در PowerShell یک آبجکت NET. است. در ادامه لیستی را از قابلیتهای PowerShell به عنوان یک زبان اسکریپتی، بررسی خواهیم کرد.
تعریف متغیر
برای تعریف یک متغیر از علامت $ قبل از نام متغیر استفاده میکنیم. نوع متغیر نیز براساس مقداری که به آن انتساب داده میشود، تعیین خواهد شد:
$stringVariable = "Hello World" $letter = 'A' $isEnabled = $false $age = 33 $height = 76 $doubleVar = 54321.21 $singleVar = 76549.11 $longVar = 2382.22 $dateVar = "July 24, 1986" $arrayVar = "A", "B", "C" $hashtableVar = @{ Name = "Sirwan"; Age = 33; }
[string]$stringVariable = "Hello World" [char]$letter = 'A' [bool]$isEnabled = $false [int]$age = 33 [decimal]$height = 76 [double]$doubleVar = 54321.21 [single]$singleVar = 76549.11 [long]$longVar = 2382.22 [DateTime]$dateVar = "July 24, 1986" [array]$arrayVar = "A", "B", "C" [hashtable]$hashtableVar = @{ Name = "Sirwan"; Age = 33; }
$global:stringVariable = "Hello World" // Or [string]$global:stringVariable = "Hello World"
عبارات شرطی
همانند دیگر زبانهای اسکریپتی، در PowerShell نیز قابلیت تعریف ساختارهای شرطی وجود دارد:
$guess = 20 switch ($guess) { {$_ -eq 20} { Write-Host "You guessed right!" } {$_ -gt 20} { Write-Host "You guessed too high!" } {$_ -lt 20} { Write-Host "You guessed too low!" } default { Write-Host "You didn't guess a number!" } } $guess = 20 if ($guess -eq 20) { Write-Host "You guessed right!" } elseif ($guess -gt 20) { Write-Host "You guessed too high!" } elseif ($guess -lt 20) { Write-Host "You guessed too low!" } else { Write-Host "You didn't guess a number!" }
$message = (Test-Path $path) ? "Path exists" : "Path not found"
حلقهها
همچنین از حالتهای مختلف loop نیز پشتیبانی میشود:
[int]$num = 10 for ($i = 1; $i -le $num; $i++) { Write-Host "`n" for ($j = 1; $j -le $num; $j++) { Write-Host -NoNewline -ForegroundColor Green ($i * $j).ToString().PadLeft(6) } } Write-Host "`n`n" [int]$counter = 1 while ($counter -le 10) { Write-Host "Hello World" $counter++ } do { Write-Host "Hello World" $counter++ } while ($counter -le 10) foreach ($i in 1..10) { Write-Host "Hello World" } $items = "Hello", "World" $items | ForEach-Object { Write-Host $_ }
آرایهها
در PowerShell به صورت پیشفرض آرایهها از نوع []System.Object در نظر گرفته میشوند. در اینجا نیز آرایهها immutable هستند. چندین روش برای ایجاد آرایه وجود دارد. در ادامه یک آرایه خالی را تعریف کردهایم:
$array = @()
$myArray = [Object[]]::new(10) $byteArray = [Byte[]]::new(100) $ipAddresses = [IPAddress[]]::new(5) $mylist = [System.Collections.Generic.List[int]]::new()
using namespace System.Collections.Generic $mylist = [List[int]]::new()
از range operator هم میتوانیم برای مقداردهی یک آرایه استفاده کرد:
$numbers = 1..10 $alphabet = "a".."z" foreach ($item in 1..10) { Write-Host "Hello World" }
$numbers = 1..10 $numbers Write-Output "".PadRight(10, "-") $numbers[1..2 + 2..4]
$colours = [System.Collections.ArrayList]@("Red", "Green", "Blue") $colours.Add("Yellow") $colours.Remove("Red")
از دیگر کالکشنهای NET. نیز میتوانید استفاده کنید؛ به عنوان مثال در مثال زیر از List برای اضافه کردن ده هزار آیتم استفاده کردهایم:
using namespace System.Collections.Generic $mylist = [List[int]]::new() Measure-Command { 1..100000 | ForEach-Object { $mylist.Add($_) } } Measure-Command { $mylist.Where({ $_ -gt 10000 }) } Measure-Command { $mylist.Contains(10000) }
Hashtable
ساختار دیگری که میتوانید استفاده کنید Hash Tableها هستند؛ از این ساختار برای ایجاد custom objects و همچنین پاس دادن پارامترها به یک command استفاده میشود: $sensors = @{ tempreture = "Temperature" humidity = "Humidity" pressure = "Pressure" light = "Light" noise = "Noise" co2 = "CO2" battery = "Battery" min_temp = "Min Temp" max_temp = "Max Temp" }
با دستور زیر میتوانید لیستی از Commandهایی که ورودیشان از نوع Hash table است را مشاهده کنید:
PS> Get-Command -ParameterType Hashtable CommandType Name Version Source ----------- ---- ------- ------ Function TabExpansion2 Cmdlet Add-Member 7.0.0.0 Microsoft.Powe… Cmdlet ConvertTo-Html 7.0.0.0 Microsoft.Powe… Cmdlet Get-Job 7.2.7.500 Microsoft.Powe… Cmdlet Invoke-Command 7.2.7.500 Microsoft.Powe… Cmdlet Invoke-RestMethod 7.0.0.0 Microsoft.Powe… Cmdlet Invoke-WebRequest 7.0.0.0 Microsoft.Powe… Cmdlet New-Object 7.0.0.0 Microsoft.Powe… Cmdlet New-PSRoleCapabilityFile 7.2.7.500 Microsoft.Powe… Cmdlet New-PSSession 7.2.7.500 Microsoft.Powe… Cmdlet Remove-Job 7.2.7.500 Microsoft.Powe… Cmdlet Select-Xml 7.0.0.0 Microsoft.Powe… Cmdlet Set-PSReadLineOption 2.1.0 PSReadLine Cmdlet Stop-Job 7.2.7.500 Microsoft.Powe… Cmdlet Wait-Job 7.2.7.500 Microsoft.Powe…
توابع
برای ایجاد توابع در PowerShell میتوانید از سینتکس زیر استفاده کنید:
function Write-HelloWorld { Write-Host "Hello World" }
تفاوت بین Function و Cmdlet چیست؟
توابع و cmdletها عملاً از لحاظ کاربرد باهم تفاوتی ندارند. تنها تفاوت آنها در نحوه ساختشان است. cmdletها با #C ساخته میشوند. به این معنا که یکسری DLL کامپایل شده هستند که در نهایت از آنها استفاده خواهیم کرد. اما توابع در PowerShell با کمک سینتکسی که اشاره شد ایجاد میشوند. توسط دستور زیر میتوانیم لیستی از توابعی را که درون سشن PowerShellمان بارگذاری شدهاند، ببینیم:
PS> Get-Command -CommandType Function
در PowerShell نیز توابع قابلیت دریافت ورودی را نیز دارند. در سادهترین حالت میتوانیم از آرایه args$ استفاده کنیم؛ دقیقاً چیزی مشابه arguments در JavaScript است:
function Write-HelloWorld { Write-Host "First Argument: $($args[0])" Write-Host "Second Argument: $($args[1])" Write-Host "Third Argument: $($args[2])" Write-Host "Fourth Argument: $($args[3])" }
function Write-HelloWorld( [string]$first, [string]$second, [string]$third, [string]$fourth ) { Write-Host "First Argument: $($first)" Write-Host "Second Argument: $($second)" Write-Host "Third Argument: $($third)" Write-Host "Fourth Argument: $($fourth)" }
در قسمت بعد در مورد Advanced Functionها صحبت خواهیم کرد و اجزای دیگر توابع را بیشتر توضیح خواهیم داد.
در ویندوز میتوانیم خروجی کنسول را به Out-GridView پایپ کنیم که در واقع یک GUI برای نمایش دادن خروجی کنسول است. این کامند فقط در ویندوز قابل استفاده است:
یک نسخه cross-platform آن نیز که مناسب کنسول است تهیه شده که میتوانید از آن استفاده کنید:
Get-Command -ParameterType Hashtable | Out-ConsoleGridview
البته به صورت پیشفرض نصب نیست و باید از طریق PowerShell Gallery آن را نصب کنید:
Install-Module -Name Microsoft.PowerShell.ConsoleGuiTools