本章主要探讨 PowerShell 核心,主要基于 Linux 平台上的 PowerShell Core 实现,实际上于 Windows PowerShell 平台上进行的实验得到的结果也不会有太大区别:linux
# 运行容器 C:\Users\chuny>docker run -it --name ps-test-base mcr.microsoft.com/powershell:centos-7 PowerShell 6.1.0 Copyright (c) Microsoft Corporation. All rights reserved. https://aka.ms/pscore6-docs Type 'help' to get help. PS /> $PSVersionTable.PSVersion Major Minor Patch PreReleaseLabel BuildLabel ----- ----- ----- --------------- ---------- 6 1 0 PS /> $PSVersionTable.OS Linux 4.9.93-linuxkit-aufs #1 SMP Wed Jun 6 16:55:56 UTC 2018
学习一门 Shell 首先要从记忆他的命令(族)作起,但 UNIX Shell 及其历史演进中的开源化特质,使得 Linux 内 bash 可调用项的命名系统支离破碎,以以下二进制为例:docker
ls
/ wc
:源于两个简写 list 与 word countuname
:源于系统调用 uname()
date
:源于非缩写的英文单词 datePS /> ls |wc -l 19 PS /> uname Linux PS /> date Sun Sep 16 06:59:33 UTC 2018
三个经常使用二进制的命名源于三种不一样的模式,非 UNIX 专业户单单从这些名字上就可能会产生恐惧感。shell
Windows 世界内,经过原住民 CMD
调用的原生应用命名也有殊途同归之妙:windows
C:\Users\chuny>taskmgr.exe C:\Users\chuny>calc.exe C:\Users\chuny>ipconfig.exe
PowerShell 采起了不一样的策略,设计了更加简单好记的 cmdlet 命名范式,cmdlet 实际上并非命令,而是托管于 .Net 平台的实例,关于 cmdlet 是什么的讨论已经远远超出了本系列的初衷,实际通常脚本工做中,造成一段脚本依靠的是粘合原生功能造成的工做流,而没必要关心这些原生功能是如何实现的。centos
cmdlet 深刻内容参考: Windows PowerShell Cmdlet Concepts
例如 Linux 中,单单一个管道的底层实现即是千行规模的,更没必要说创建在各类库上面的二进制了。bash
Linux 管道的实现思路: How Linux pipes work under the hood
所以,cmdlet 即平台相关的原生功能的抽象,以以下的一段获取时间的代码片断为例:ide
PS /> $dateNow = Get-Date PS /> $dateNow Sunday, September 16, 2018 6:55:39 AM PS /> $dateNow.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True DateTime System.ValueType PS /> $dateNow.GetType().Name DateTime PS /> $dateNow Sunday, September 16, 2018 6:55:39 AM
Get-Date
为一个标准的预置 PowerShell cmdlet,
PowerShell 使用动-名命名范式,即每一个 cmdlet 标准名称都由一个标识意图的动词、连字符以及一个标的物名词组成。函数
预置 PowerShell cmdlet:因为 PowerShell 启动时默认的载入
Microsoft.PowerShell.Utility
模块,所以其中的 cmdlet 是开箱即用的,或者说是
预置的。
PowerShell 同时内建了高效的帮助系统供用户自学 cmdlet 等的使用方式,以搜索日期相关的 cmdlet 为例:post
PS /> Get-Help -Category cmdlet Date Name Category Module Synopsis ---- -------- ------ -------- Update-Help Cmdlet Microsoft.PowerShell.Core ... Get-Date Cmdlet Microsoft.PowerShell.U... ... Set-Date Cmdlet Microsoft.PowerShell.U... ... Update-FormatData Cmdlet Microsoft.PowerShell.U... ... Update-TypeData Cmdlet Microsoft.PowerShell.U... ...
Get-Help
即为 PowerShell 体系中的标准帮助函数,相似于 UNIX 世界中的 man
,Get-Help -Category cmdlet Date
表明在 cmdlet 这一种类中搜索 Date
这一字符串相关的项目,Get-help
可经过查看自身得到基本帮助,即 Get-Help Get-Help
。学习
同时,PowerShell 也提供了一个 cmdlet 以供精确的命令搜索:
PS /> Get-Command -Noun Date CommandType Name Version Source ----------- ---- ------- ------ Cmdlet Get-Date 6.1.0.0 Microsoft.PowerShell.Utility Cmdlet Set-Date 6.1.0.0 Microsoft.PowerShell.Utility
这次对 Date
的搜索精确到了获取标的物名词可用的命令种类,获取到了 Date
的 getter
与 setter
。
同时,PowerShell 对于 cmdlet 也是大小写不敏感的,例如:
PS /> Get-DaTe Sunday, September 16, 2018 7:51:50 AM PS /> get-date Sunday, September 16, 2018 7:51:52 AM
但做为更好的工程实践,建议严格遵照 cmdlet 原始写法,实际上交互式 Shell 中只需在输入 cmdlet 后利用 Tab 补全便可得到原始写法。
PowerShell 也提供别名系统用以简化命令输入,但建议只在交互式 Shell 中使用,例以下行中的 gal
又是什么呢:
PS /> (gal).Name.Length 110 # 实际上 gal 即 Get-Alias 的别名,直接运行 gal 能够得到现已加载的模块中存在的别名列表 PS /> (Get-Alias gal).Definition Get-Alias
若是生产环境脚本中大量出现这样的别名势必大大影响可读性。
$dateNow = Get-Date
中的 $dateNow
声明一个名为 dateNow
的变量,变量亦能够在创建时不指定值:
PS /> $newVar PS /> $newVar # 无输出
变量名能够包含下划线字符,也能够是任何字母数字字符。变量在 使用时,始终使用$ 字符加变量名称指定变量。
$dateNow = Get-Date
将等式右方计算返回的对象赋予左方,注意此时左方为一个肯定的实例,二者具有一样的类型,以以下的片断为例,二者类型相同,然而值不同,$dateNow
已是最近一次赋值时绑定的对象,Get-Date
将使用默认值初始化并返回一个匿名对象:
PS /> $dateNow.GetTypeCode() DateTime PS /> (Get-Date).GetTypeCode() DateTime # $dateNow 是一个实例 PS /> $dateNow.GetType.IsInstance True # 两个匿名对象的 Hash 值不一样 PS /> (Get-Date).GetHashCode() 433633629 PS /> (Get-Date).GetHashCode() 431809023
PowerShell 中的变量存储对象,所以其中对变量的操做将遵循面向对象的方式进行。
Get-Member
cmdlet 用于获取变量(对象)中的成员,例如对于 $dateNow
其具有属性 Year
与成员方法 ToType
:
PS /> $dateNow | Get-Member -Name Year TypeName: System.DateTime Name MemberType Definition ---- ---------- ---------- Year Property int Year {get;} PS /> $dateNow | Get-Member -Name ToType TypeName: System.DateTime Name MemberType Definition ---- ---------- ---------- ToType Method System.Object IConvertible.ToType(type conversionType, System.IFormatProvider provider)
所以,对于对象成员的调用也经过 .
运算符实现:
# 方法调用 PS /> $dateNow.ToString() 9/16/18 7:23:57 AM # 成员调用(即调用该成员的 getter 方法,如不存在直接返回值) PS /> $dateNow.Year 2018 # 成员更新(即调用该成员的 setter 方法,如不存在直接写值,此处该属性已经被声明为只读属性,因此没法更改) PS /> $dateNow.Year = -2 'Year' is a ReadOnly property. At line:1 char:1 + $dateNow.Year = -2 + ~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [], RuntimeException + FullyQualifiedErrorId : PropertyAssignmentException
对于 PowerShell 工做流的造成也将围绕对象与管道展开,以一段获取并格式化生成列表的 AJAX 请求为例:
根据快递 100 提供的开放查询 API,能够查询到某快递公司某单号的具体递送信息,以下为例:
# 定义变量 $baseUrl = "www.kuaidi100.com/query" $scheme = "http" $company = "yuantong" $postId = "11111111111" # 发送请求 $ret = Invoke-RestMethod -Uri ($scheme + "://" + $baseUrl + "?type=" + $company + "&postid=" + $postId) # Get-Member 检查该返回对象中的成员 PS /> $ret | Get-Member TypeName: System.Management.Automation.PSCustomObject Name MemberType Definition ---- ---------- ---------- Equals Method bool Equals(System.Object obj) GetHashCode Method int GetHashCode() GetType Method type GetType() ToString Method string ToString() com NoteProperty string com=yuantong condition NoteProperty string condition=00 data NoteProperty Object[] data=System.Object[] ischeck NoteProperty string ischeck=0 message NoteProperty string message=ok nu NoteProperty string nu=11111111111 state NoteProperty string state=0 status NoteProperty string status=200 # $ret 的返回值为 200 SUCCESS PS /> $ret.status 200 # 经过管道链接,即可输出只包含固定字段的记录中的某些项(例如前五项) PS /> $ret.data | Format-Table -Property Time, Context | select -First 5 time context ---- ------- 2018-09-14 10:20:06 贾岗社区28号楼1单元101室妈妈驿站已发出自提短信,请上门自提,联系电话0371-60997919 2018-09-14 10:19:06 快件已到达贾岗社区28号楼1单元101室妈妈驿站,联系电话0371-60997919 2018-08-23 09:58:40 华伟家园东门头房快递服务中心妈妈驿站已发出自提短信,请上门自 提,联系电话17662528999