[TOC]
0x05 流(Flow)控制 描述: 当你从编写 PowerShell 单行命令转为编写脚本时,实际复杂程度没有想象的那么高。脚本只是在 PowerShell 控制台中以交互方式运行的相同或类似命令,只不过它们保存为 .PS1 文件;
0.条件判断 Where-Object 语句 描述: Where-Object会对集合逐个过滤,将符合条件的结果保留, 别名是 ?
与 Where
。
基础示例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 Get-Process | Where-Object {$_ .Name -eq "notepad" } Get-Process | Where-Object {$_ .company -like '*Microsoft*' } | select Name,Description,Company Get-Service | ? {$_ .Name -like "B*" } Get-Service | where {$_ .Name -like "B*" } 1..10 | ? { $_ % 2 -eq 0 } 1..10 | where { $_ % 2 -eq 0 -and $_ % 4 -eq 0 }
Tips : 通过Get-Alias -Definition Where-Object
利用cmdlet查看其别名
[TOC]
0x05 流(Flow)控制 描述: 当你从编写 PowerShell 单行命令转为编写脚本时,实际复杂程度没有想象的那么高。脚本只是在 PowerShell 控制台中以交互方式运行的相同或类似命令,只不过它们保存为 .PS1 文件;
0.条件判断 Where-Object 语句 描述: Where-Object会对集合逐个过滤,将符合条件的结果保留, 别名是 ?
与 Where
。
基础示例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 Get-Process | Where-Object {$_ .Name -eq "notepad" } Get-Process | Where-Object {$_ .company -like '*Microsoft*' } | select Name,Description,Company Get-Service | ? {$_ .Name -like "B*" } Get-Service | where {$_ .Name -like "B*" } 1..10 | ? { $_ % 2 -eq 0 } 1..10 | where { $_ % 2 -eq 0 -and $_ % 4 -eq 0 }
Tips : 通过Get-Alias -Definition Where-Object
利用cmdlet查看其别名
IF 语句 if…else 与 if…elseif…else 语句
基础示例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 $week =(Get-Date ).DayOfWeekif ( $week -eq 'Thursday' ) { Write-Output "今天是星期四(Thur),当前时间:" Get-Date } else { Write-Output "今天不是星期四" } if ( $week -eq 'Monday' ) { Write-Output "unhappy,今天是星期1" } elseif ( $week -eq 'Thesday' ) { Write-Output "unhappy,今天是星期2" } elseif ( $week -eq 'Wednesday' ) { Write-Output "unhappy,今天是星期3" } elseif ( $week -eq 'Thursday' ) { Write-Output "unhappy,今天是星期4" } elseif ( $week -eq 'Friday' ) { Write-Output "unhappy,今天是星期5" } elseif ( $week -eq 'Saturday' ) { Write-Output "Happy,今天是星期6" } else { Write-Output "Happy,今天是星期天" }
Switch 判断语句 基础示例: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 $value =6switch($value ) { 1 {"I come from Beijing" } 2 {"I come from Shanghai" } 3 {"I come from Tianjin" } 6 {"I come from Chongqing" } } $value =18switch($value ) { {$_ -lt 10} {"小于10" } 10 {"等于10" } {$_ -gt 10} {"大于10" } } $value =-7switch($value ) { {($_ -lt 10) -and ( $_ -gt 0) } {"小于10" } 10 {"等于10" } {$_ -gt 10} {"大于10" } Default {"没有匹配条件" } } $value =99switch($value ) { {$_ -lt 5 } { "小于5" ; break } {$_ -gt 0 } { "大于0" ; break } {$_ -lt 100} { "小于100" ; break } Default {"没有匹配条件" } } $domain ="Www.weiyigeek.top" switch -case ($domain ) { "Www.weiyigeek.top" {"Ok 1" } "www.weiyiGeek.com" {"Ok 2" } "WWW.weiyiGeegk.COM" {"Ok 3" } } $domain ="www.mossfly.com" switch -wildcard($domain ) { "*" {"匹配'*'" } "*.com" {"匹配*.top" } "*.*.*" {"匹配*.*.*" } } $mail ="master@weiyigeek.top" switch -regex ($mail ) { "^master" {"master" } "top$" {"top结尾" } "d{1,3}.d{1,3}.d{1,3}.d{1,3}" {"IP地址" } } $value =100..999switch($value ) { { [Math]::Pow($_ %10,3) + [Math]::Pow( [Math]::Truncate($_ %100/10) ,3) + [Math]::Pow( [Math]::Truncate($_ /100) , 3) -eq $_ } {$_ } }
1.循环执行 描述: PowerShell 优势是确定了如何为某个项执行某些操作后,就可以很容易地为数百个项执行相同的任务。 只需使用 PowerShell 中多种不同类型的循环之一循环访问这些项即可。
ForEach-Object 语句 描述: ForEach-Object 是用于循环访问管道中的项的 cmdlet,例如使用 PowerShell 单行命令然后通过管道流式处理对象。其实是ForEach-Object可以接受三个脚本块用于管道的流模式处理,分别代表begin,process和end
。
基础示例: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 WeiyiGeek> 1 ..10 | ForEach-Object { Write-Host -NoNewline "当前 $_ 次序 ->" ; $_ * 10 } 当前 1 次序 ->10 当前 2 次序 ->20 当前 3 次序 ->30 当前 4 次序 ->40 当前 5 次序 ->50 当前 6 次序 ->60 当前 7 次序 ->70 当前 8 次序 ->80 当前 9 次序 ->90 当前 10 次序 ->100 'ActiveDirectory' , 'SQLServer' | ForEach-Object {Get-Command -Module $_ } | Group-Object -Property ModuleName -NoElement | Sort-Object -Property Count -Descending 'Get-ComputerInfo' , 'Test-Path' | ForEach-Object {Get-Command -Name $_ } | Group-Object -Property ModuleName -NoElement | Sort-Object -Property Count -Descending 1 ..5 | % { Write-Host -NoNewline "第{$_ }次时间:" ; Get-Date ;Start-Sleep 1 } foreach ( $a in 1 ..3 ) { foreach ( $b in 1 ..3 ) { Write-Host -NoNewline "$a + $b = " ; $a + $B } } foreach ($Computer in 'DC01' , 'WEB01' ) { Get-ADComputer -Identity $Computer } ls | ForEach-Object {"文件名:{0} 文件大小{1}KB: " -f $_ .Name,($_ .length/1 kb).tostring()} 文件名:a.html 文件大小65.99609375 KB: 文件名:a.txt 文件大小25.765625 KB: 文件名:alias 文件大小11.77734375 KB:
For 语句 描述: 当指定的条件为 true 时,for 循环会进行循环访问,在PS中应该使用较少。1 2 3 4 5 6 for ($i = 1; $i -lt 5; $i ++) { Write-Output "Sleeping for $i seconds" Start-Sleep -Seconds $i }
Do 语句 描述: PowerShell 中有两个不同的 do 循环。
指定的条件为 false 时, Do Until 运行。
指定的条件为 True 时, Do While 运行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 $number = Get-Random -Minimum 1 -Maximum 10 do { $guess = Read-Host -Prompt "What's your guess?" if ($guess -lt $number ) { Write-Output 'Too low!' } elseif ($guess -gt $number ) { Write-Output 'Too high!' } } until ($guess -eq $number )$number = Get-Random -Minimum 1 -Maximum 10 do { $guess = Read-Host -Prompt "What's your guess?" if ($guess -lt $number ) { Write-Output 'Too low!' } elseif ($guess -gt $number ) { Write-Output 'Too high!' } } while ($guess -ne $number )
Tips : Do 循环始终运行至少一次,因为将在循环结束时计算条件的结果。
While 语句 描述: 与 Do While 循环类似,只要指定的条件为 true,While 循环就会运行。 但差别在于 While 循环会在运行任何代码之前,计算循环顶部条件的结果, 如果条件计算结果为 false,它就不会运行代码块中的内容。
1 2 3 4 5 6 7 8 9 10 $week = (Get-Date).DayOfWeekwhile ( $week -eq 'Thursday' ) { Write-Output "今天是星期三将在此基础上加1天: " $date = (Get-Date).AddDays(1) break } Write-Output $date
Tips : 从 PowerShell 版本 3.0 开始,可以使用 $PSItem 而不是 $。 但我发现,大多数经验丰富的 PowerShell 用户仍更喜欢使用 $ ,因为它向后兼容,需要输入的内容更少。
Tips : 使用 foreach 关键字时,必须先将所有项存储在内存中,然后才能循环访问这些项,如果不知道要处理的项数,此操作可能会很困难。
Switch 循环语句 描述: Switch 本是多路分支的关键字,但是在Powershell中由于Switch支持集合,所以也可以使用它进行循环处理。
基础示例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 Switch (10..1) { Default { " n = $_ " } } $nums = 10..7Switch ($nums ) { {($_ % 2) -eq 0} {"$_ 偶数" } {($_ % 2) -ne 0} {"$_ 奇数" } }
2.终止操作 描述: 如何在循环中当满足某些条件时跳出循环, 我们可以采用以下关键字 Break、Continue 和 Return
。
1) Break 旨在中断循环。它通常与 switch 语句一起使用。
2) Continue 旨在跳到循环的下一次迭代。它通常与 while 语句一起使用。
3) Return 旨在退出现有作用域。
基础案例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 for ($i = 1; $i -lt 5; $i ++) { Write-Output "Sleeping for $i seconds" Start-Sleep -Seconds $i break } while ($i -lt 5) { $i += 1 if ($i -eq 3) { continue } Write-Output $i } $number = 1..10foreach ($n in $number ) { if ($n -ge 4) { Return $n } }
0x06 PS数组和哈希表 描述: 我们理解的数组是存储同一类型的数据集合,而Powershel中可以设置为多种数据格式。PS会将命令执行后的结果文本按每一行作为元素存为数组,在命令的返回值不止一个结果时,PS也会自动把结果存储为数组。
PS 中数组的特征:
1.数组的多态性: PS中数组像变量一样如果数组中元素的类型为弱类型,默认可以存储不同类型的值。
2.数组的有序性: PS数组在内存中是顺序存储的,所以数组的大小必须是确定的方便分配存储空间。
3.数组的引用性: 使用默认的的赋值运算符在两个变量之间赋值只是复制了一个引用两个变量共享同一份数据,则改变一个另一个也会相应的改变;
常规数组 描述: 前面我们说明Powershell会把命令执行返回文本按每一行作为元素存为数组
基础示例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 "WeiyiGeek" -is [array] False "WeiyiGeek" .toCharArray() -is [array]True PS > $IP =IPCONFIG PS > $IP -is [array] True PS > $IP .getType() PS > $IP .Count 32 PS > $IP [4] PS > $IP [8]
思考为什么不愿把IPconfig返回的结果称为对象? 答:因为它不是真正Cmdlet命令,真正的Powershell命令返回的数组元素可不止一个字符串,它是一个内容丰富的对象。
1.数组创建 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 PS > $array =@() $a =,"WeiyiGeek" PS > $array =1,2,3,4,5 PS > $array =1..5 PS > $array =1,1.2,"String" PS > $array -is [array] PS > $array .Count PS C:\Users\WeiyiGeek> $array = @(1,'hello' ) PS C:\Users\WeiyiGeek> $array PS C:\Users\WeiyiGeek> $array .GetType() PS > $arr =1..3 PS > $arr +=5..8 PS > $arr 1 2 3 5 6 7 8 PS C:Powershell> $books ="元素1" ,"元素2" ,"元素3" PS C:Powershell> $books +="元素4" PS C:Powershell> $books 元素1 元素2 元素3 元素4 PS > $arr = 1..3 PS > $arr = $arr [1..2] + 4..6 PS > $arr 2 3 4 5 6
Tips : 命令返回的数据是数组类型,数组的每一个元素存放的是一个System.IO.DirectoryInfo
对象。
2.数组访问 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 PS > $arr PS > $arr [0] 1 PS > $arr [($arr .Count-1)] PS > $arr [-1] 8 PS > $arr [0,1,3,5] 1 2 5 7 PS > $arr [($arr .Count)..0] 8 7 6 5 3 2 1
3.复制数组 描述:复制数组最好使用Clone()方法,除非有特殊需求。1 2 3 4 5 6 7 8 9 10 11 12 13 14 PS > $arr =1..3 PS > $arr1 =$arr PS > $arr1 .Equals($arr ) True PS > $arr2 =$arr .Clone() PS > $arr2 .Equals($arr ) False PS > $arr2 [0]=1024 PS > $arr2 1024 2 3
数组类型 描述:数组一般具有多态性,如果你不指定元素的具体类型,解释器会自动选择合适的类型存储每个元素
。
如果要统一限制所有元素的类型,可是使用类型名和一对方括号作为数组变量的类型。
每当赋值时会自动类型检查, 如果目标数据类型不能转换成功,就会抛出一个异常。
基础示例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 PS > [int[]] $num = @() PS > $num += 1024 PS > $num += 3.1415926 PS > $num += 999 PS > $num 1024 3 999 [string[]] $str = @() $str += "Name" $str += "is" $str += "WeiyiGeek" $str += 1024 $str .GetType().fullnameSystem.String[]
哈希表(Hash) 描述:哈希表存放的是键值对(Key-Value)
,在哈希表中不再仅仅限制使用数字寻址,可以使用任意类型的数据类型寻址
。
Tips: 在创建哈希表时就使用数组,因为创建数组和哈希表的的元素关键字不冲突一个是逗号,一个是分号
。
基础实例: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 PS > $hash =@{ Name="WeiyiGeek" ;Age="15" } PS > $hash ['Name' ] WeiyiGeek PS > $hash .Keys Age Name PS > $hash .Values 15 WeiyiGeek PS > $hash .Count 2 PS > $hash =@{ Name="WeiyiGeek" ;Age="15" ; Books="C" ,"C++" ,"PYTHON" } PS > $hash .Sex="Woman" PS > $hash PS > $hash .Name="weiyi" PS > $hash .remove("Books" ) PS > $hash PS C:Powershell> Dir | Format-Table FullName,Mode PS > $column1 = @{expression="Name" ; width=30;label="filename" ; alignment="left" } PS > $column2 = @{expression="LastWriteTime" ; width=40;label="last modification" ; alignment="right" } PS > ls | Format-Table $column1 , $column2 $SysPrivilege = @{ name = "weiyigeek" result = @() } $demo1 = $SysPrivilege $Hash = $SysPrivilege .Clone() $SysPrivilege .age=18$demo1 $Hash
补充说明: 在Hash键值对的与文件中的某一行字符进行验证是否匹配时采用.Equals()
时返回为False,一定要注意文件中是否带有\"\"
在进行匹配时也必须带上其”单引号字符进行匹配,坑呀(一下午就荒废在这里了)1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 $TestString = @{value='WeiyiGeek' ;}"WeiyiGeek" .Equals("$($TestString.value) " ) "WeiyiGeek" .Equals($TestString .value) "WeiyiGeek" .Equals($TestString .value.ToString()) "WeiyiGeek" -eq "$($TestString.value) " "WeiyiGeek" -eq "$TestString .value" $TestString = @{value='"WeiyiGeek_admin"' ;value1='"Guest"' }"WeiyiGeek_admin" AdministratorIsPublic IsSerial Name BaseType -------- -------- ---- -------- True True String System.Object True True String System.Object "Guest" GuestTrue True String System.Object True True String System.Object
0x07 函数(Function) 描述: 函数就是将大大小小的命令组合成一个集合里面进行执行,有利于提高代码复用以及简练代码量;
函数三原则:
简短:函数名简短,并且显而易见。
聚合:函数可以完成多个操作。
封装和扩展:将一批Powershell语句进行封装,实现全新的功能需求。
函数结构 描述: 由三部分组成:函数名,参数,函数体1 2 3 4 Function 函数名称 (args[]) { code; }
函数定义 描述: 主要针对函数的创建、调用、更新和删除。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 function Test-conn { Test-Connection -Count 2 -ComputerName $args } Set-Alias tc test -conn PS C:\PS> tc localhost Function getHostName { Write-Host -NoNewline "当前机器名称: " HOSTNAME.EXE } getHostName $function :getHostName $function :getHostName | Out-File getHostName.ps1PS C:\Users\WeiyiGeek> .\getHostName.ps1 当前机器名称: WeiyiGeek Remove-Item function :getHostName
函数参数 描述: PS 函数可以接受参数并对参数进行处理,函数的参数有3个特性:
1.任意参数:内部变量 $args
接受函数调用时接受的参数,它是一个数组类型。
2.命名参数:函数的每一个参数可以分配一个名称,在调用时通过名称指定对应的参数。
3.预定义参数:函数在定义参数时可以指定默认值,如果调用时没有专门指定参数的值,就会保持默认值。
(1) 万能参数 描述 : $args 变量是万能参数它可以识别任意个参数,在PS编程开发中非常有用。
基础示例: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 function say-Hello{ if ($args .Count -eq 0){ "No argument!" }else { $args | foreach {"Hello,$($_) " } } } PS C:\Users\WeiyiGeek> say-Hello No argument! PS C:\Users\WeiyiGeek> say-Hello WeiyiGeek Hello,WeiyiGeek PS C:\Users\WeiyiGeek> say-Hello WeiyiGeek Computer Hello,WeiyiGeek Hello,Computer function Add { $sum =0 $args | foreach { $sum += $_ } $sum } PS C:\Users\WeiyiGeek> Add 1 2 3 4 5 15
(2) 参数名称设置 描述: 我们可以设置指定名称的传入参数的名称并进行调用, 它可以有两种形式进行调用一是通过顺序传入、二是通过指定参数名称;
注意: 传入参数我们可以对其设置强弱类型的参数, 由于函数的参数解释器比较傲慢,它对你提供的参数的信息完全不关心。它只会粗略地将参数进行分割,并且最大限度的进行自动类型转换。在实际编程过程中我们常常需要限定用户输入类型(防止搞破坏)
基础示例: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 function StringContact($str1 ,$str2 ){ return $str1 +$str2 } StringContact Weiyi Geek StringContact -str1 Weiyi -str2 Geek StringContact 16 50 function subtract([int]$value1 ,[int]$value2 ){ return $value1 -$value2 } subtract 3 5 function subtract([double]$value1 ,[double]$value2 ){ return $value1 -$value2 } subtract 8.8 7.9 function DayOfWeek([datetime]$date ){ return $date .DayOfWeek } DayofWeek '1927-8-1' DayofWeek 2008-8-1
(3) 参数定义默认值 描述: 我们可以对传入的参数设置默认的值,当且仅当没有传入参数时。
基础示例: 1 2 3 4 5 6 7 8 function defaultStringContact($str1 ="WeiyiGeek" ,$str2 ="-Computer" ){ return $str1 +$str2 } PS C:\Users\WeiyiGeek> defaultStringContact Good Luck PS C:\Users\WeiyiGeek> defaultStringContact
(4) Switch 参数 描述: Powershell 函数最简单的参数类型为布尔类型,除了使用Bool类型,也可以使用Switch关键字。
基础示例: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 function tryReverse( [switch]$try , [string]$source ){ [string]$target ="" if ($try ) { for ( [int]$i = $source .length -1 ; $i -ge 0 ;$i --) { $target += $source [$i ] } return $target } return $source } tryReverse -source www.weiyigeek.top tryReverse -try $true -source www.weiyigeek.top
函数返值 描述: PS 它的函数可以有多个返回值, 如果你直接调用函数,返回值会在控制台输出,当然我们通常是将结果存储在一个变量中进一步处理。
基础示例: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 function Square([double]$num ){ return $num *$num } function gbMeasure($amount ){ "$amount GB=$($amount ) GB" "$amount GB=$($amount *1gb/1mb) MB" "$amount GB=$($amount *1gb/1kb) KB" "$amount GB=$($amount *1gb) B" } gbMeasure 1 $result =gbMeasure 1 $result $result =gbMeasure 1 $result [3 ] Function lottery([int]$number =1 ){ $rand = New-Object system.random For ($i =1 ; $i -le $number ; $i ++) { $rand .next(1 ,50 ) } } $result = lottery$result -is [array] $result = lottery 10 $result -is [array] Function Test(){ Write-Host "Try to calculate." "3.1415926" Write-Debug "Done." } $value $DebugPreference ="Continue" $value =Test
Tips: 如果一个函数返回一个值像其它编程语言一样,这个值包括她的类型信息会直接返回 Tips: 如果遇到多个返回值,Powershell会将所有的返回值自动构造成一个Object数组。可以通过索引访问数组。
Tips: 使用Write-Debug有两个优势,首先调试信息会自动高亮显示,便于分析。其次这些调试信息只会在调试模式开启时输出,控制起来更加方便。当然最重要的是这些临时信息无论什么时候也不会混淆在返回值。
Tips: 如果你想通过显示调试信息调试函数可以开启调试模式, 如果关闭调试模式,这些调试信息自然不会输出。1 2 3 4 $DebugPreference ="Continue" $DebugPreference ="SilentlyContinue"
函数支持 描述: Powershell已经提供了许多用户能够使用的预定义函数, 我们可以通过Function:进行查看有哪些预定义函数。
Powershell中的这些预定义的函数可以做很多重要的工作,例如我们常常使用的命令其实都是PS的预定义函数。
X: 调用Set-Location定位到指定的驱动器根目录
prompt 返回提示文本
Clear-Host 清除屏幕的缓存
help,man 查看命令的帮助文档
mkdir,md 通过new-Item创建子目录
more 分屏输出管道结果
TabExpansion Tab键的自动完成提示
基础示例: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 > dir function : | ft -AutoSize ... $Function:A: $Function:psEdit ${function :Clear-Host } (dir function :).count 201
自定义终端字符串 描述: 我们可以通过覆盖prompt
函数来重写命令行显示,简单示例1如下:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 function prompt{ $host .ui.rawui.WindowTitle = "Line: " + $host .UI.RawUI.CursorPosition.Y + " " + $env:USERNAME + " " + $Host .Name + " " + $Host .Version $curPos = $host .ui.rawui.CursorPosition $widthPos = $host .ui.rawui.WindowSize.Width $newPos = $curPos $newPos .X+=( $widthPos - 24 ) $host .ui.rawui.CursorPosition = $newPos Write-Host ("{0:D} {0:T}" -f (Get-Date )) -foregroundcolor Yellow $host .ui.rawui.CursorPosition = $curPos Write-Host ("[" +$(whoami) + "] - PS " + $(get-location ) +">" ) -nonewline -foregroundcolor Green " " } title web New-Item -path $profile -type file -forcecode $profile function Set-WindowTitle { $host .UI.RawUI.WindowTitle = [string]::Join(" " , $args ) } Set-Alias -name "title" -value Set-WindowTitle[weiyigeek\weiyigeek] - PS C:\Users\WeiyiGeek> whoami 2021 年4 月18 日 13 :44 :50 weiyigeek\weiyigeek
weiyigeek.top-命令行标题及命令行显示设置
简单示例2: 使用WindowsPrincipal 辨别当前用户是否使用了管理员权限,1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 $CurrentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent()$principal = new-object System.Security.principal.windowsprincipal($CurrentUser )$global :Admin = $principal .IsInRole( [System.Security.Principal.WindowsBuiltInRole]::Administrator)Function prompt { Write-Host ("PS " + $(get-location)) -nonewline If ($admin ) { $oldtitle = $host .ui.rawui.WindowTitle If (!$oldtitle .StartsWith("Administrator: " )) { $host .ui.rawui.WindowTitle ="Administrator: " + $oldtitle } Write-Host ">" -nonewline -foregroundcolor Red } Else { Write-Host ">" -nonewline } return " " } 没有管理员权限时,标题栏文本:Windows Powershell 有管理员权限时,标题栏文本: Administrator :管理员 : Windows Powershell
管道函数 描述: 一个函数能够访问和进一步处理另外一条命令的结果,就是我们前面所讲的管道。
Tips: 这里在补充一哈管道的两种模式,一种是顺序处理模式,一种是流处理模式
(1) 低效率的顺序模式:$input
默认情况下你的函数不是真正支持管道,只能对前一个命令执行后的结果处理,即前一个命令执行的结果通过被自动保存在$input变量(数组)
中,它可以包含许多元素,一个元素,甚至一个元素都没有,这取决于具体的环境。
基础示例: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 Function output { $input } PS > 1,2,3 | output PS > dir | output Function funPipeline { $oldcolor = $host .ui.rawui.ForegroundColor Foreach ($element in $input ) { write-Host $element .name If ($element .name.toLower().endsWith(".png" )) { $host .ui.Rawui.ForegroundColor = "red" }Else{ $host .ui.Rawui.ForegroundColor = $oldcolor } $element } $host .ui.Rawui.ForegroundColor = $oldcolor } [weiyigeek\weiyigeek] - PS C:\Users\WeiyiGeek\Pictures> ls | funPipeline 2021年4月18日 14:17:47
weiyigeek.top-管道函数的处理
(2) 高效率的流模式(过滤器): 针对之前funPipeline函数,你只需要替换”function” 关键字 为 “filter”
,它就会开始流模式处理,这样你再也不用过分的担心忍受程序的无休止的响应和崩溃的危险。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 filter filPipeline { $oldcolor = $host .ui.rawui.ForegroundColor If ($_ .name.toLower().endsWith(".png" )){ $host .ui.Rawui.ForegroundColor = "Darkred" }Else{ $host .ui.Rawui.ForegroundColor = $oldcolor } $_ $host .ui.Rawui.ForegroundColor = $oldcolor } Dir . -recurse | filPipeline
Q: 如何开发真正的管道函数
答: 如果一个函数内部使用了管道可以定义三个基础的代码块实现函数:第一步完成函数的初始化(Begin
),完成函数执行的预备步骤;第二步处理递归调用所得的结果(Process
), 最后进行收尾工作(End
);
基础示例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 Function filterPipeline{ begin { $oldcolor = $host .ui.rawui.ForegroundColor } process { If ($_ .name.toLower().endsWith(".exe" )) { $host .ui.Rawui.ForegroundColor = "red" } Else { $host .ui.Rawui.ForegroundColor = $oldcolor } $_ } end { $host .ui.Rawui.ForegroundColor = $oldcolor } } ls C:\WINDOWS\System32\ | filterPipeline
Tips : 管道的低效率顺序模式在处理大容量数据时很容易出现问题,其结果是巨大的内存占用和进程等待。 Tips : 如果你的函数支持高效率的流模式,在处理管道结果时仅占用很小的内存。 Tips : 过滤器在函数中属于高级应用 (特殊的函数),因为它可以立即处理管道结果的每一个元素, 但是过滤器必须每次重复执行预定义命令的结果。