原创
最近更新: 2024/09/07 20:35

Windows PowerShell语言入门

参考链接:PowerShell官方文档

基本概念与语法

PowerShell 是微软 Windows 系统自带的升级版原生开发语言,参考 Linux 的 shell 进行的重做,提供比 cmd 更加完善的功能。

可以通过Get-Help来获取基本的帮助。

注释

PowerShell 使用#来引导单行注释。每一行从注释符号开始到行末不会被执行。多行注释用<# …… #>来标识。

hello world

> Write-Output helloworld
helloworld

续行符

在交互式界面中,一般而言,换行意味着执行已经输入的代码,不过在续行符处换行不会直接执行代码,而是另起一行继续输入。续航符包括管道符|、逗号,、左括号([{、左引号'"、等于号=等。

数据类型和变量

PowerShell 常见数据类型有

  • 基本类型:整型 Int、浮点 Double、字符型 Char、日期型 DateTime、布尔型 Boolean 等
  • 组合类型:列表、字典
  • 对象:包括字符串等

PowerShell 使用$来定义和引用一个变量。PowerShell 的变量是动态类型的,也可以用方括号[]来限定变量的数据类型。

[int]$a = 1.1	# a = 1

数值

整型int和浮点型double是 PowerShell 的基本类型,PowerShell 也提供对象类型的整型和浮点型。

# 定义和赋值
$a = 1 			# a会自动识别为整型
$b = $a + 0.1 	# b = 1.1 整型和浮点型计算,结果为浮点型
# 用括号来将基本数据类型包装为对象
(1).CompareTo(2)	# -1
1.CompareTo(2)		# 报错

布尔型

布尔型bool变量只有真和假两个取值,需要用$true$false来引用。其他类型变量转换为布尔型时,0和空值会转换为假,其他转换为真。

日期型

日期型datetime用于记录时间信息,可以进行日期和时间的操作,并转化为格式化字符串。

$a = Get-Date
$a.ToString("yyyy-MM-dd HH:mm:ss")

字符串

PowerShell 的字符串string实际上是一种对象。

# 定义和赋值
> $a = "asd"
# 引用
> $b = $a + 1 	# b = "asd1" 整型和字符串进行运算,结果为字符串

PowerShell 也提供基本的字符串处理函数,如 split()、trim()、contains()等。

集合

PowerShell 支持定义集合操作,集合是动态类型的,允许存放不同类型的变量。

# 集合有三种定义方式
> $a = 1,2,3
> $a = ("a","b")
> $a = @(1,2,3)
# 集合支持嵌套
> $b = $a, 1, "a"
# 集合的大小是固定的,要往集合中添加元素,要用+=
> $a.Add(1) # 报错
> $a += 2 	# 此时会生成一个新的集合替代原有的集合

集合是有序的,可以用[]方括号来引用集合的某一项。

集合本身是对象类型的。使用Get-Member查看集合的类型,将打印集合中所有项的数据类型介绍。

PowerShell 支持 .Net 框架中更高级的集合类型

$a = New-Object System.Collections.ArrayList
$a.Add(1)

字典

PowerShell 提供键值对字典(System.Collections.Hashtable)类型,键会被默认解释为字符串类型。

> $d = @{1=2;3=4}
> $d
Name                           Value
----                           -----
1                              2
3                              4

字典项可以通过点号(引用运算符)或者方括号进行赋值和引用,点号引用时不需要双引号,方括号引用时需要双引号。严格来说,方括号引用的泛用性更好,因为存在部分情况无法使用点号引用。

# 以下两种方式等价
$ass.qerqererqw = "qqww222"
$ass["qerqererqw"] = "qqww222"
$ass["1q"] = 1 # ass.1q 的引用方法会报错

运算符

算数运算符

PowerShell 支持对数字(整型、浮点型)进行常见的算数运算操作,包括+-*/%(整数取余)等。

字符串、数组支持+(连接)、*(重复)运算。

不同数据类型之间进行运算,会将运算符右边的值转换为左边的数据类型后再进行计算。

赋值运算符

最基础的赋值运算符是=,PowerShell 同时提供+=-=*=/=%=等复合赋值运算符。

此外,PowerShell 支持自增++、自减--运算符。

比较运算符

PowerShell 包含许多比较运算符,用于逻辑运算或查找符合一定要求的值,常用于条件语句和where语句匹配筛选场景。如同其他编程语言一样,比较运算的结果是布尔值。比较运算符清单如下:

运算符 含义 运算符 含义
-eq 等于 -ne 不等于
-gt 大于 -ge 大于或等于
-lt 小于 -le 小于或等于
-Like 使用 * 通配符进行匹配 -NotLike 不使用 * 通配符进行匹配
-Match 匹配指定的正则表达式 -NotMatch 不匹配指定的正则表达式
-Contains 确定集合中是否包含指定的值 -NotContains 确定集合是否不包含特定值
-In 确定指定的值是否在集合中 -NotIn 确定指定的值是否不在集合中
-Replace 替换指定的值

以上比较均不区分大小写,如需要区分大小写,则应在运算符前加c,如将-eq改为-ceq

> "a" -eq "A" 		# True
> "a" -ceq "A" 		# False
> 1 -ge 2 			# False
> 1 -in (1,2,3) 	# True

逻辑运算符

布尔型变量可以使用与-and、或-or、非-not、亦或-xor等基本的逻辑运算。

> (2 -gt 3) -and (1 -eq 1) 	# False
> $true -or (2 -gt 3) 		# True
> -not $false 				# True
> $true -xor $false			# True

类型运算符

方括号[]可以在变量、参数声明时限定其类型,或在引用一个变量时强制转换其类型。也通过-as来进行强制类型转换,如果类型无法进行转换,会报错。

[int]$a = 1
[int]$a = "1"
[int]$a = [int]"1"
$a = "1111" -as [int]
[int]$a = "a" # 会报错

可以通过-isisnot来判断某个变量是否是某个类型,结果为布尔型变量。

if ($a -is [int]) {echo 1}

其他运算符

引用运算符.:可以用来引用对象的属性、方法,集合或字典的某一项。

范围操作符..:可以简便地记录一定范围内的数字序列

$a = 1..5 # $a = (1, 2, 3, 4, 5)

数字简记符号KBMBGBTB:可以简便记录2的整10次方数字,1KB=1024=2^10,1MB=10241024=2^20,1GB=10241024*1024=2^30

流程控制语句

Powershell 一般情况下是从上往下顺序执行所有语句,同时也提供条件语句和循环语句。

条件语句

if-else语句:当括号中的运算结果为真时,执行if语句,为假时执行else语句

if (1 -is [int]) {echo "int"}
else {echo "Not int"}

switch语句:当括号中的运算结果等于下列某个选项时,执行该选项对应的语句块。如果没有命中任一选项,执行default语句块。

switch($a){
	1 {echo 1}
	2 {echo 2}
	default {echo default}
}

循环语句

for语句:括号中包含三个子语句,语句1用于初始化循环变量;语句2在每次循环开始前执行,为真则展开循环,为假则跳出循环;语句3在每次循环结束后执行。

for ($i = 0;$i -lt 10;$i++) {echo $i}

foreach语句:枚举一个集合中的所有元素,并在循环体中引用它们。

 foreach($i in 1..9) {echo $i}

while语句:当括号中的语句为真时,执行循环体。

while($a -gt 0) {
	echo $a;
	$a--
}

do-while语句:先执行一遍循环体,再判断当括号中的语句,为真时,继续执行循环体。

do {
	echo $a;
	$a--
} while($a -gt 0);

函数

可以用以下语法定义和调用函数

# 无参数函数
function func{
	echo "func"
}
# 有参数函数
function add($a, $b) {
	return $a + $b
}
# 可以指定函数的参数类型
function add([int]$a, [int]$b) {
	return $a + $b
}

函数的完整定义方式,可以设置参数是否必要和参数的顺序(通过Mandatory标记)、参数的验证方式(长度、范围等),常见的验证内容有:

  • [ValidateNotNullOrEmpty()]:参数非空
  • [ValidateRange(1,5)]:参数数值范围
  • [ValidateCount(1,5)]:参数数量范围
  • [ValidatePattern("aaa*")]:正则表达式匹配验证
  • [ValidateSet("a", "b", "c")]:枚举验证
function func {
	param (
		[parameter(Mandatory = $true, Position = 0)]
		[ValidateRange(1,5)] [string]$a,
		[parameter(Mandatory = $true, Position = 1)]
		[validateset("a","b")] $b
	)
	return $a + $b
}
# 调用函数
add 1 2
add -a 1 -b 2

数据输入

Powershell 提供交互式及文件输入渠道。

交互式输入

Read-Host指令允许终端从键盘读入用户输入,并将输入解释为字符串。-AsSecureString参数可以将输入内容以*形式展示,且以 SecureString 格式存储。

> $username = Read-Host "请输入用户名:"
> $password = Read-Host "请输入密码:" -AsSecureString
# AsSecureString参数可以将输入内容以`*`形式展示并加密存储,不过只能用来传输给.Net进程

弹窗输入登录凭证

Get-Credential指令会弹出一个对话框,接受用户名口令输入,并存储为 PSCredential 对象。

文件读取

Get-Content指令接受一个文件路径,并将内容以字符串形式读入。读入的字符串可以通过方括号来选择行数。

> cat .\2.txt -First 10 # 前10行内容
> cat .\2.txt -Tail 10 	# 尾部10行内容
> (cat .\2.txt)[3,6] 	# 第3行和第6行内容
> (cat .\2.txt)[3..6] 	# 第3行至第6行内容

Get-Content可以自动识别 XML 格式文件(文档第一行需要有 XML 声明)。

Select-String指令在Get-Content基础上,提供字符串模式匹配功能,可以直接从文件中读取所需的字符串。

Import-CSV指令会将识别 csv 表格,并将第一行解释为属性名称,第二行起每一行解释为一个对象。可以自定义分隔符,默认是英文逗号。

Import-Clixml指令可以读取 Clixml 文件,一般用来读取Export-Clixml输出的文件。

数据输出与格式转化

常见的数据输出指令如下:

  • Set-Content覆盖写入。
  • Add-Content追加写入。
  • Out-File将数据写入文件。与Set-ContentAdd-Content功能相近。
  • Export-CSV可以将对象输出为 CSV 文件。
  • Export-Clixml可以将对象输出为 Clixml 文件。
  • ConvertTo-Html可以将对象转换为 HTML 表格形式。
  • Out-GridView可以将对象呈现在窗口化的表格中,并提供内置筛选器。

cmdlet命令

PowerShell cmdlet 命令是 PowerShell提供的轻量化调用模块,基本上以动作名开头,用-引导形参(使用Linux的形式,与cmd的/不同)。

可以用Get-Command来获取所有支持的命令清单,或特定命令的信息。也可以通过COMMAND名称 -?的方式获取单条命令的帮助信息。

  • 参数类型有 required、named、positional 和 switch 四种。
  • 一个参数有多个值的,一般用逗号,分隔,*为通配符。

PowerShell 在交互式命令行中提供自动补全功能,使用 Tab 键可以自动补全命令名称、参数名称、参数值和文件路径等。

管道

PowerShell 单行是一个连续管道,通过管道符|可以连接多个 cmdlet,将前一个命令的输出作为后一个命令的输入参数。

一个重要的问题是,哪些命令可以在管道右侧接受管道输出,且输出会作为哪一个参数被接受。此处可以通过help COMMAND-NAME -Full命令来获取相应信息。help COMMAND-NAME -Parameter *也有相似的效果。

> help write -full
# 以下内容是输出
名称
    Write-Output
语法
    Write-Output [-InputObject] <psobject[]>  [<CommonParameters>]
参数
    -InputObject <psobject[]>
        是否必需?                    True
        位置?                        0
        是否接受管道输入?            True (ByValue, FromRemainingArguments)
        参数集名称          (所有)
        别名                     无
        动态?                    false

    -NoEnumerate
        是否必需?                    False
        位置?                        已命名
        是否接受管道输入?            False
        参数集名称          (所有)
        别名                     无
        动态?                    false

代码示例中可以看到,“参数”部分“是否接受管道输入?”项标识了某个参数是否可以接受管道输入,以及接受管道输入的方式。其中:

  • ByValue 意味着这个参数可以直接接受数值作为输入
  • ByPropertyName 意味着这个命令可以接受(官方的说法是“绑定”)一个对象,并对象的属性作为指令同名参数的输入
  • FromRemainingArguments 意味着参数接受命令中未分配给函数其他参数的所有参数值

此外,也可以用括号方式进行 cmdlet 的嵌套,括号内的命令会优先执行,并作为括号外的命令的参数。

别名机制

标准命令较长,不易输入,为了简化命令,兼容旧版 cmd 命令,并提供 Linux 风格命令扩展,PowerShell提供了别名机制,可以在命令行中输入Get-Alias查看。常用的别名有:

别名 标准命令 别名 标准命令
% ForEach-Object ?/where Where-Object
cat/gc/type Get-Content cd/sl Set-Location
clear/cls Clear-Host curl Invoke-WebRequest
compare/diff Compare-Object dir/ls Get-ChildItem
echo/write Write-Output man/help Get-Help
md mkdir del/rm/rmdir Remove-Item
move/mv/mi Move-Item copy/cp/cpi Copy-Item
ps Get-Process sort Sort-Object
ft Format-Table fl Format-List

可以用Set-Alias设置别名,一般建议在配置文件中设置别名。

PowerShell 对象

PowerShell 一个巨大的变化在于,绝大多数 cmdlet 的返回值是一个.NET Framework 对象,而不是单纯的字符串。这样有利于对结果进行筛选、计算、排序等进一步处理。

事实上,字符串在 PowerShell 中也是以对象形式存在的。

成员类型

对象拥有属性(Property)和方法(Method)两类成员。获取特定属性或者调用特定方法的方式与一般面向对象的编程语言一致,通过.()来实现。

# 结束名字为“cmd”的进程
> (Get-Process| Where name -like "cmd").Kill()
# 获取字符串长度
> "123456".length
6

属性(Property)又可以细分为以下几类:

  • NoteProperty:具有静态值的属性,可以直接赋值。较为常用。
  • AliasProperty:给现有的属性定义一个新名称。较为常用。
  • ScriptProperty:其值是脚本输出的属性。较为常用。
  • ParameterizedProperty:具有参数和参数值的属性。
  • CodeProperty:一种可引用 .NET Framework 类的静态属性的属性。

创建对象

可以用New-Object命令创建新的对象。

> $no = New-Object psobject
> $no | 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()

也可以用以下语法快速创建对象

# 普通对象
$obj = [pscustomobject]@{
      Name = 'Doris'
      Age = '20'
}
# 日期对象
$date = [Datetime]"1970-1-1" # 1970年1月1日 0:00:00
$date = "1970-1-1" -as [Datetime] # 1970年1月1日 0:00:00
$date = [Datetime]"1970-1-1 19:21:5" # 1970年1月1日 19:21:05

可以用Add-Member命令给对象增加成员。如果 PowerShell 预定义的属性中没有我们需要的值,需要通过计算得到,或者需要给某个属性改名、更改数据类型以适配管道需要,我们可以自定义一个属性。详见下方示例代码。

查看和展示

查看

可以将对象传输给Get-Member命令来查看其类型、具有的属性和方法。对象的属性有很多,默认打印在输出流中的属性不一定全。可以将返回值传输给Select-Object命令并指定-Property等参数来查看该类对象的其他属性。如果返回值中包含多个对象,可以用Where-Object进行筛选

Get-Service |
  Where-Object CanPauseAndContinue -eq $true |
    Select-Object -Property *

在展示时增加属性

如果 PowerShell 预定义的属性中没有我们需要展示的值,需要通过计算得到,或者需要给某个属性改名以适配管道需要,我们可以自定义一个属性。

基本语法是@{name="自定义属性的名称"; expression={自定义属性的计算方法}},其中,自定义属性的名称是一个字符串,计算方法是一个表达式或者值,表达式中可以用$_来枚举引用对象自身。详见下方示例代码。

格式化展示

标准输出流会将对象以格式化形式展示,其中

  • 大多数命令使用表格方式格式化输出数据,也可以用Format-Table来手动将输出格式改为表格。
  • Select-Object使用列表方式展示数据,会将对象属性按行输出,多个对象通过空行分隔。也可以用Format-List来手动将输出格式改为列表。
  • Format-Wide会将所有数据项名称平铺排列。
  • Format-Custom是自定义显示格式,比较复杂,很少用到。

详见下方示例代码。

示例代码

> $no = Get-Service -Name w32time
> $no | Add-Member -MemberType NoteProperty -Name noteP -Value 1234 # 此处会将1234的值理解为int
> $no | Add-Member -MemberType AliasProperty -Name strNoteP -Value noteP -secondValue string # noteP的别名,但是字符串
> $no | Add-Member -MemberType ScriptProperty -Name scriptP -Value {$this.name} # 脚本中用$this引用自身
> $no | select name, noteP, @{name="noteP+1";expression={$_.noteP+1}},
        strNoteP, @{name="strNoteP+1";expression={$_.strNoteP+1}}, scriptP |
		Format-Table

Name    noteP noteP+1 strNoteP strNoteP+1 scriptP
----    ----- ------- -------- ---------- -------
w32time  1234    1235 1234     12341      w32time

排序和统计

排序

将输出传输给Sort-Object可以对其进行排序。默认是对名称进行顺序排列,可以通过-Property参数选择排序的属性,通过-desc来倒序排序。

> Get-ChildItem|sort -Property LastWriteTime -Desc

统计

Measure-Object是 PowerShell 提供的一个统计工具,可以统计输出内容中某个属性的计数、总和、平均数、最大值、最小值等。-Character可以让这个工具统计文档中的字符数量、行数等。

> Get-ChildItem|measure -Property Length -sum -max -min -Average

分组

Group-Object可以将对象进行分组统计。

> Get-ChildItem|group -Property mode

ps1脚本文件

PowerShell 脚本文件是以.ps1作为扩展名的文本文件,可以实现PowerShell命令的批量运行。

执行权限

如果出现不允许执行 PowerShell 脚本的情况,可以用管理员权限打开 PowerShell 命令行,并输入

set-ExecutionPolicy RemoteSigned

并在跳出来的选项中选“全是”即可。

如果要关闭运行权限,则输入

set-ExecutionPolicy Default

脚本参数

PowerShell 脚本文件可以带参数,参数存储在变量$args中。$args是一个字符串集合。

if ($args.count -eq 0) {
	echo "No Argument"
} else {
	foreach($a in $args) {
		echo $a
	}
}

配置文件

PowerShell 的配置文件路径存储在 $PROFILE变量中,是一个 PowerShell 脚本文件。

评论区