Powershell 的基础使用IV 函数与注释
Powershell 的基础使用IV 函数与注释
前言
这里是相关基础知识的函数与注释篇.
基本函数语法规则
见基本函数1
2
3
4
5
6
7function [<scope:>]<name> [([type]$parameter1[,[type]$parameter2])]
{
begin {<statement list>}
process {<statement list>}
end {<statement list>}
clean {<statement list>}
}
用例
根据定义, 可以很快写出一个基础的函数1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21function Get-Time([string]$Zone = '中国') {
# 获取与 UTC 的偏移量
$offset = Get-TimeZone -ListAvailable | where-Object { $_.StandardName.Contains($Zone) -or $_.DisplayName.Contains($Zone) } | Select-Object -First 1
if (($null -eq $offset) -or ('' -eq $offset)) {
Write-Error "请求的地区不存在: $Zone"
}
# UTC 时间
[datetime]$utc = Get-Date -AsUTC
$gs = [regex]::Match($offset.BaseUtcOffset, '(?<h>[+-]{0,1}\d{2}):(?<m>[+-]{0,1}\d{2}):(?<s>[+-]{0,1}\d{2})').Groups
[int]$hour = $gs['h'].Value
[int]$minute = $gs['m'].Value
[int]$second = $gs['s'].Value
return $utc.AddHours($hour).AddMinutes($minute).AddSeconds($second)
}
Get-Time
Get-Time -$Zone '俄罗斯'
Get-Time '澳大利亚'
$hk = '香港' | Get-Time
[DateTimeOffset]::new($hk).ToUnixTimeMilliseconds()
或者以下形式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
37function Get-Time {
param(
[parameter(ValueFromPipeline)]
[string]$Zone = '中国'
)
begin {
# UTC 时间
[datetime]$utc = Get-Date -AsUTC
}
process {
# 获取与 UTC 的偏移量
$offset = Get-TimeZone -ListAvailable | where-Object { $_.StandardName.Contains($Zone) -or $_.DisplayName.Contains($Zone) } | Select-Object -First 1
if (($null -eq $offset) -or ('' -eq $offset)) {
Write-Error "请求的地区不存在: $Zone"
}
$gs = [regex]::Match($offset.BaseUtcOffset, '(?<h>[+-]{0,1}\d{2}):(?<m>[+-]{0,1}\d{2}):(?<s>[+-]{0,1}\d{2})').Groups
$out = $utc.AddHours($gs['h'].Value).AddMinutes($gs['m'].Value).AddSeconds($gs['s'].Value)
$out | Add-Member -MemberType NoteProperty -Name Zone -Value $Zone
$out | Add-Member -MemberType NoteProperty -Name Present -Value $out.ToString()
return $out
}
end {}
}
Get-Time
Get-Time -Zone 中国
@('悉尼' , '东京', '俄罗斯') | Get-Time | Select-Object -Property @('Zone', 'Present') | Format-Table
$h = Get-Time '香港'
[DateTimeOffset]::new($h).ToUnixTimeMilliseconds()
Get-Time
Get-Time -Zone 中国
@('悉尼' , '东京', '俄罗斯') | Get-Time | Select-Object -Property @('Zone', 'Present') | Format-Table
$h = Get-Time '香港'
[DateTimeOffset]::new($h).ToUnixTimeMilliseconds()
这个函数输出对应地区的时间, 还输出了香港地区的时间戳:1
2
3
4
5
6
7
8
9
10
112024年6月16日 10:46:35
2024年6月16日 10:46:35
Zone Present
---- -------
悉尼 2024/6/16 12:46:35
东京 2024/6/16 11:46:35
俄罗斯 2024/6/16 4:46:35
1718534795735
一些小结
- 函数可以使用第一种最简化的版本, 默认支持管道
- 可以变换到第二个版本, 需要在 process 块执行, 同时注意到需要高级参数
ValueFromPipeline
,where-Object
中的过滤当前对象默认是$_
, 而管道块当前迭代对象也是$_
, 使用该参数之后函数的管道值将指向参数$Zone
- begin 在多管道时只运行一次, 这里使用了共享参数
$utc
, 见 增加开关参数
增加开关参数
增加一个标记,打印当前请求的地区信息
修改上边的代码, 增加入参, 修改 begin
与 process
, clean
块中的代码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
41function Get-Time {
param(
[parameter(ValueFromPipeline)]
[string]$Zone = '中国',
[switch]
$PrintReq
)
begin {
# UTC 时间
[datetime]$utc = Get-Date -AsUTC
if ($PrintReq) {
Write-Host "`e[33m初始化 UTC 的时间`e[0m"
}
}
process {
if ($PrintReq) {
Write-Host "`e[34m正在获取 [$Zone] 地区的时间`e[0m"
}
# 获取与 UTC 的偏移量
$offset = Get-TimeZone -ListAvailable | where-Object { $_.StandardName.Contains($Zone) -or $_.DisplayName.Contains($Zone) } | Select-Object -First 1
if (($null -eq $offset) -or ('' -eq $offset)) {
Write-Error "请求的地区不存在: $Zone"
}
$gs = [regex]::Match($offset.BaseUtcOffset, '(?<h>[+-]{0,1}\d{2}):(?<m>[+-]{0,1}\d{2}):(?<s>[+-]{0,1}\d{2})').Groups
$out = $utc.AddHours($gs['h'].Value).AddMinutes($gs['m'].Value).AddSeconds($gs['s'].Value)
$out |
Add-Member -MemberType NoteProperty -Name Zone -Value $Zone -PassThru |
Add-Member -MemberType NoteProperty -Name Present -Value $out.ToString()
return $out
}
end {
if ($PrintReq) {
Write-Host "`e[35m关闭函数`e[0m"
}
}
}
Get-Time -PrintReq
@('悉尼' , '东京', '俄罗斯') | Get-Time -PrintReq | Select-Object -Property @('Zone', 'Present') | Format-Table
上边的输出为:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17初始化 UTC 的时间
正在获取 [中国] 地区的时间
2024年6月16日 11:00:26
关闭函数
初始化 UTC 的时间
正在获取 [悉尼] 地区的时间
正在获取 [东京] 地区的时间
正在获取 [俄罗斯] 地区的时间
关闭函数
Zone Present
---- -------
悉尼 2024/6/16 13:00:26
东京 2024/6/16 12:00:26
俄罗斯 2024/6/16 5:00:26
一些小结
- 可以观察到,
初始化
只输出了两次, 在管道流的初始化,关闭
同理, 如果只使用Get-Time
,$PrintReq
会初始化为False
- 使用开关参数避免了手动输入
-PrintReq $true
的尴尬局面 -PassThru
也是一个开关参数, 返回管道中的$_
对象
增加参数校验
避免手动检查抛错, 选择用高级参数限制输入, 对以上的函数, 仅做 非空检查即可
修改之后的函数为: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
50function Get-Time {
param(
[parameter(ValueFromPipeline)]
[ValidateNotNullOrWhiteSpace()]
[string]$Zone = '中国',
[switch]
$PrintReq
)
begin {
# UTC 时间
[datetime]$utc = Get-Date -AsUTC
if ($PrintReq) {
Write-Host "`e[33m初始化 UTC 的时间`e[0m"
}
}
process {
if ($PrintReq) {
Write-Host "`e[34m正在获取 [$Zone] 地区的时间`e[0m"
}
# 获取与 UTC 的偏移量
$offset = Get-TimeZone -ListAvailable | where-Object { $_.StandardName.Contains($Zone) -or $_.DisplayName.Contains($Zone) } | Select-Object -First 1
if (($null -eq $offset) -or ('' -eq $offset)) {
Write-Error "请求的地区不存在: $Zone"
}
$gs = [regex]::Match($offset.BaseUtcOffset, '(?<h>[+-]{0,1}\d{2}):(?<m>[+-]{0,1}\d{2}):(?<s>[+-]{0,1}\d{2})').Groups
$out = $utc.AddHours($gs['h'].Value).AddMinutes($gs['m'].Value).AddSeconds($gs['s'].Value)
$out |
Add-Member -MemberType NoteProperty -Name Zone -Value $Zone -PassThru |
Add-Member -MemberType NoteProperty -Name Present -Value $out.ToString()
return $out
}
end {
if ($PrintReq) {
Write-Host "`e[35m关闭函数`e[0m"
}
}
}
Get-Time
try {
Get-Time -Zone ' '
}
catch [System.Management.Automation.ParameterBindingException] {
[System.Management.Automation.ParameterBindingException]$e = $_.Exception;
Write-Host "检测到参数错误, 错误参数: $($e.ParameterName)"
}
catch {
Write-Host "检测到运行错误: $($_.Exception.Message)"
}
使用 Get-Time - ' '
将得到一个校验错误: 如下1
22024年6月16日 11:47:00
检测到参数错误, 错误参数: Zone
一些小结
- 参数校验以 Validate 开始
- 参数校验抛出的错误为 ParameterBindingException 类
- 使用
try--catch
捕捉错误
完善函数声明与注释
以下是完整的函数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<#
<#
.SYNOPSIS
获取地区时间
.DESCRIPTION
根据指定地区, 获取地区时间, 默认为中国
.PARAMETER Zone
指定地区
.PARAMETER PrintReq
输出 debug 信息
.OUTPUTS
datetime 地区时间
.LINK
https://learn.microsoft.com/en-us/dotnet/api/system.datetime?view=net-8.0
.LINK
https://learn.microsoft.com/zh-cn/powershell/module/microsoft.powershell.management/get-timezone?view=powershell-7.4
.EXAMPLE
Get-Time
.EXAMPLE
Get-Time '美国'
.EXAMPLE
Get-Time -Zone '美国'
.INPUTS
地区信息
#>
function Get-Time {
param(
[parameter(ValueFromPipeline, Mandatory = $false, Position = 0)]
[ValidateNotNullOrWhiteSpace()]
[string]$Zone = '中国',
[switch]
$PrintReq
)
begin {
# UTC 时间
[datetime]$utc = Get-Date -AsUTC
if ($PrintReq) {
Write-Host "`e[33m初始化 UTC 的时间`e[0m"
}
}
process {
if ($PrintReq) {
Write-Host "`e[34m正在获取 [$Zone] 地区的时间`e[0m"
}
# 获取与 UTC 的偏移量
$offset = Get-TimeZone -ListAvailable | where-Object { $_.StandardName.Contains($Zone) -or $_.DisplayName.Contains($Zone) } | Select-Object -First 1
if (($null -eq $offset) -or ('' -eq $offset)) {
throw "请求的地区不存在: $Zone"
}
$gs = [regex]::Match($offset.BaseUtcOffset, '(?<h>[+-]{0,1}\d{2}):(?<m>[+-]{0,1}\d{2}):(?<s>[+-]{0,1}\d{2})').Groups
$out = $utc.AddHours($gs['h'].Value).AddMinutes($gs['m'].Value).AddSeconds($gs['s'].Value)
$out |
Add-Member -MemberType NoteProperty -Name Zone -Value $Zone -PassThru |
Add-Member -MemberType NoteProperty -Name Present -Value $out.ToString()
return $out
}
end {
if ($PrintReq) {
Write-Host "`e[35m关闭函数`e[0m"
}
}
}
try {
Get-Time '未知'
}
catch [System.Management.Automation.ParameterBindingException] {
[System.Management.Automation.ParameterBindingException]$e = $_.Exception;
Write-Host "检测到参数错误, 错误参数: $($e.ParameterName)"
}
catch {
Write-Host "检测到运行错误: $($_.Exception.Message)"
}
Get-Help Get-Time -Full
以及输出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检测到运行错误: 请求的地区不存在: 未知
NAME
Get-Time
SYNOPSIS
获取地区时间
SYNTAX
Get-Time [[-Zone] <String>] [-PrintReq] [<CommonParameters>]
DESCRIPTION
根据指定地区, 获取地区时间, 默认为中国
PARAMETERS
-Zone <String>
指定地区
Required? false
Position? 1
Default value 中国
Accept pipeline input? true (ByValue)
Accept wildcard characters? false
-PrintReq [<SwitchParameter>]
输出 debug 信息
Required? false
Position? named
Default value False
Accept pipeline input? false
Accept wildcard characters? false
<CommonParameters>
This cmdlet supports the common parameters: Verbose, Debug,
ErrorAction, ErrorVariable, WarningAction, WarningVariable,
OutBuffer, PipelineVariable, and OutVariable. For more information, see
about_CommonParameters (https://go.microsoft.com/fwlink/?LinkID=113216).
INPUTS
地区信息
OUTPUTS
datetime 地区时间
-------------------------- EXAMPLE 1 --------------------------
PS > Get-Time
-------------------------- EXAMPLE 2 --------------------------
PS > Get-Time '美国'
-------------------------- EXAMPLE 3 --------------------------
PS > Get-Time -Zone '美国'
RELATED LINKS
https://learn.microsoft.com/en-us/dotnet/api/system.datetime?view=net-8.0
https://learn.microsoft.com/zh-cn/powershell/module/microsoft.powershell.management/get-timezone?view=powershell-7.4