Powershell 毕业年份计算在减去 -2 时中断
Powershell Year of Graduation Calculation Breaks When Subtracting -2
我必须根据年级推断学生的毕业年份。他们的学生证号码中有 2 位数的毕业年份,但由于学生被推迟和其他基于身份证号码的异常情况,这有时被证明是不准确的。
我写了一个 powershell 脚本来为我做这件事,作为一个更大的脚本的一部分,用于获取从 powerschool 导出的 CSV,并根据他们的毕业年份检查他们在活动目录中的位置。我遇到问题的脚本部分如下:
function GradeToYog($grade){ # converts grade number to year of grad because IDNUM is not a reliable indicator of grad year
if($grade -ne $null){
# get current date
$date = Get-Date
# account for time of year, add 1yr offset to grad year if september or later
$offset = 0
if($date.month -ge 9){
$offset = 1
}
# Account for placement of extended-stay students such as SPED kids
if($grade -gt 12){
$grade = 12
}
return ($date.year + 12 + $offset - $grade)
} else {
return "Invalid entry."
}
}
这适用于 -1 年级(学前班)到 12 年级,但是当我针对 -2 测试它时它会中断:
PS C:\> GradeToYog 12
2022
PS C:\> GradeToYog 9
2025
PS C:\> GradeToYog 6
2028
PS C:\> GradeToYog 3
2031
PS C:\> GradeToYog 1
2033
PS C:\> GradeToYog 0
2034
PS C:\> GradeToYog -1
2035
PS C:\> GradeToYog -2
2022
奇怪的是,如果我在 powershell 中根据相同的逻辑测试预期值,它会起作用:
PS C:\> 2022 + 12 + 0 - -2
2036
我搜索了类似的问题,但要么我没有正确搜索它,要么似乎没有 powershell 错误地减去 '-2' 的实例
注意:我无法重现您的具体症状,但以下建议仍然值得听取。
Type-constrain 你的 $grade
参数确保它是一个 number:
# Make sure that $grade is an [int] (System.Int32) value
function GradeToYog([int] $grade) { # ...
# Alternative syntax, with a param(...) block,
# which makes it easier to use validation attributes.
function GradeToYog {
param(
[ValidateRange(-2, 15)] # Constrain the range of allowable numbers.
[int] $grade
)
# ...
}
无约束参数实际上与[object] $grade
相同,即它可以接收任何类型的对象。
PowerShell 推断 某些类型来自未加引号的参数,例如 2
和 -2
,也许令人惊讶的是,2
变成了 [int]
,而 -2
变为 [string]
(强制后者被解释为 [int]
ad hoc,将其作为 (-2)
).
许多 PowerShell 运算符,例如 -eq
/ ne
和 -lt
/ -le
/ -gt
/ ge
都可以同时运行字符串和数字,通常是 LHS 操作数的类型决定了整个操作的数据类型。
这是一个例子,说明这会产生什么影响:
2 -lt 10 # $true
'2' -lt 10 # !! $false, due to *lexical* comparison
我必须根据年级推断学生的毕业年份。他们的学生证号码中有 2 位数的毕业年份,但由于学生被推迟和其他基于身份证号码的异常情况,这有时被证明是不准确的。
我写了一个 powershell 脚本来为我做这件事,作为一个更大的脚本的一部分,用于获取从 powerschool 导出的 CSV,并根据他们的毕业年份检查他们在活动目录中的位置。我遇到问题的脚本部分如下:
function GradeToYog($grade){ # converts grade number to year of grad because IDNUM is not a reliable indicator of grad year
if($grade -ne $null){
# get current date
$date = Get-Date
# account for time of year, add 1yr offset to grad year if september or later
$offset = 0
if($date.month -ge 9){
$offset = 1
}
# Account for placement of extended-stay students such as SPED kids
if($grade -gt 12){
$grade = 12
}
return ($date.year + 12 + $offset - $grade)
} else {
return "Invalid entry."
}
}
这适用于 -1 年级(学前班)到 12 年级,但是当我针对 -2 测试它时它会中断:
PS C:\> GradeToYog 12
2022
PS C:\> GradeToYog 9
2025
PS C:\> GradeToYog 6
2028
PS C:\> GradeToYog 3
2031
PS C:\> GradeToYog 1
2033
PS C:\> GradeToYog 0
2034
PS C:\> GradeToYog -1
2035
PS C:\> GradeToYog -2
2022
奇怪的是,如果我在 powershell 中根据相同的逻辑测试预期值,它会起作用:
PS C:\> 2022 + 12 + 0 - -2
2036
我搜索了类似的问题,但要么我没有正确搜索它,要么似乎没有 powershell 错误地减去 '-2' 的实例
注意:我无法重现您的具体症状,但以下建议仍然值得听取。
Type-constrain 你的 $grade
参数确保它是一个 number:
# Make sure that $grade is an [int] (System.Int32) value
function GradeToYog([int] $grade) { # ...
# Alternative syntax, with a param(...) block,
# which makes it easier to use validation attributes.
function GradeToYog {
param(
[ValidateRange(-2, 15)] # Constrain the range of allowable numbers.
[int] $grade
)
# ...
}
无约束参数实际上与[object] $grade
相同,即它可以接收任何类型的对象。
PowerShell 推断 某些类型来自未加引号的参数,例如 2
和 -2
,也许令人惊讶的是,2
变成了 [int]
,而 -2
变为 [string]
(强制后者被解释为 [int]
ad hoc,将其作为 (-2)
).
许多 PowerShell 运算符,例如 -eq
/ ne
和 -lt
/ -le
/ -gt
/ ge
都可以同时运行字符串和数字,通常是 LHS 操作数的类型决定了整个操作的数据类型。
这是一个例子,说明这会产生什么影响:
2 -lt 10 # $true
'2' -lt 10 # !! $false, due to *lexical* comparison