我正在嘗試處理有關何時進行PowerShell轉換以及何時用戶需要明確他們想要什么的檔案/證據。一個有點相關的問題,here,有一個斷開的鏈接,可能解釋了型別將被調整的情況。但是,有很多類似問題的實體(即,將 astring與 an進行比較int)——例如,當您通過 獲得一個數字時Read-Host,您實際上獲得了一個字串。
具體來說,盡管我發現某些機制似乎可以很好地處理數字的字串表示形式 - 但我想了解這是否真的是因為他們將其作為數字處理,或者輸出是否在外觀上正確但錯誤在引擎蓋下。這是一個具體的例子,所以問題是關于Measure-Object它如何處理計算Sum字串屬性的。
PS > $Example = Import-Csv .\Example.csv
PS > $Example
Procedure_Code : 123456789
CPT_Code : J3490
Modifier :
Service_Date : 02/01/2020
Revenue_Code : 259
Units : -100.00
Amount : 55.00
Procedure_Code : 123456789
CPT_Code : J3490
Modifier :
Service_Date : 02/02/2020
Revenue_Code : 259
Units : 100.00
Amount : 55.00
PS > [Math]::Sign($Example[0].Units)
-1
PS > $Example | Measure-Object Amount -Sum
Count : 2
Sum : 110
Property : Amount
PS > $Example | ForEach-Object { $Sum = $Sum $_.Amount} ; Write-Host "$($Sum)"
55.0055.00 #Plus sign concatenates strings
PS > $Example | ForEach-Object { $Sum = $Sum [int]$_.Amount} ; Write-Host "$($Sum)"
110 #Expected result if casting the string into an integer type before adding
所以基本上它看起來很[Math]::Sign()有效(盡管據我所知它不接受字串),并且Measure-Object比簡單的加號更聰明地處理字串。但是Measure-Object將我的字串轉換為[int]? 如果我使用小數的例子,答案會更精確,所以也許它是[single]?
怎么Measure-Object做才能得到正確的答案,我什么時候不應該相信它?
uj5u.com熱心網友回復:
我不確定這是最重要的和最終的答案,但它適用于我好奇的事情。對于許多“快速腳本”場景,您可能會使用類似的東西Measure-Object- 您可能會得到您正在尋找的正確答案,盡管可能比其他方法慢。
Measure-Object如果無法轉換 CSV 物件中的字串值之一,則似乎特別[double]適用于Sum、Average和StandardDeviation并且確實會引發錯誤。
我仍然有點驚訝,它完全[Math]::Sign()適用于字串,但似乎很高興
if (_measureAverage || _measureSum || _measureStandardDeviation)
{
double numValue = 0.0;
if (!LanguagePrimitives.TryConvertTo(objValue, out numValue))
{
_nonNumericError = true;
ErrorRecord errorRecord = new(
PSTraceSource.NewInvalidOperationException(MeasureObjectStrings.NonNumericInputObject, objValue),
"NonNumericInputObject",
ErrorCategory.InvalidType,
objValue);
WriteError(errorRecord);
return;
}
AnalyzeNumber(numValue, stat);
}
uj5u.com熱心網友回復:
Measure-Object是一種特殊情況,因為 cmdlet 的特定邏輯執行自動型別轉換,而不是 PowerShell 自己的一般自動轉換發生在使用運算子的背景關系中,例如 ,將引數傳遞給命令,呼叫.NET 方法,例如[Math]::Sign(),并使用值作為條件。
正如您自己的答案所暗示的那樣,Measure-Object呼叫 PowerShell 的常規自動型別轉換使用的相同代碼;這些將在下面討論。
PowerShell 中的自動型別轉換:
通常,PowerShell總是嘗試自動型別轉換- 熟悉 C# 的人的一個陷阱是,如果目標型別最終是不同的,則即使是顯式強制轉換(例如[double] '1.2')也可能無法實作。[1]
支持的轉換:
- 除了支持 .NET 的型別轉換,PowerShell 還實作了一些內置的自定義轉換,并通過自定義轉換類和屬性類支持用戶定義的轉換 - 請參閱此答案。
與字串相互轉換時的數字轉換和文化敏感性:
- 通常,PowerShell 使用文化不變轉換,例如,僅
.被識別為表示浮點數的“數字字串”中的小數點。 - 本答案涵蓋了字串到數字的轉換,包括如何選擇特定的數字資料型別。
- 此答案涵蓋了字串轉換(包括從數字轉換)。
按背景關系自動型別轉換:
運算元(運算子引數):
一些運算子,例如
-replaceand-match,只對字串進行操作,在這種情況下,運算元總是被轉換為字串(總是成功):42 -replace 2, '!'yields'4!':42和2都被隱式轉換為字串。
其他的,例如
-and\,只對數字進行操作,在這種情況下,運算元總是被轉換為數字(可能會失敗):'10' - '2'產率8,一個[int]
然而其它諸如
和*,可以在操作任一字串或數字,并且它是在LHS的型別確定操作型別:'10' 2產率'102',該級聯字串的'10'與到字串的轉換數目的2。- 相反,
10 '2'產量12,所述加成數10和轉號碼轉換字串'2'。
有關更多資訊,請參閱此答案以獲取更多資訊。
命令引數:
如果目標引數具有特定型別(除了
[object]或[psobject]),PowerShell 將嘗試轉換。否則,對于文字引數,型別是從文字表示中推斷出來的;例如
42,作為[int], 和'42'作為[string].
用作條件的值,例如在
if陳述句中:- 根據定義,條件必須是布林值(型別
[bool]),并且 PowerShell[bool]使用本答案底部部分中描述的規則自動將任何型別的值轉換為。
- 根據定義,條件必須是布林值(型別
方法引數:
.NET 方法引數的自動型別轉換可能很棘手,因為可能必須考慮多個多載,并且 - 如果引數不是預期的型別 - PowerShell 必須根據支持的型別轉換找到最佳多載 - 而且它選擇哪一個可能并不明顯。
執行[Math]::Sign(按原樣()呼叫,沒有)顯示了 8(!) 種不同的多載,適用于各種數字型別。
More insidiously, the introduction of additional .NET-method overloads in future .NET versions can break existing PowerShell code, if the new overload then happens to be the best match in a given invocation.
A high-profile example is the [string] type's Split() method - see the bottom section of this answer.
Therefore, for long-term code stability:
Avoid .NET methods in favor of PowerShell-native commands, if possible.
Otherwise, if type conversion is necessary, use casts (e.g.
[Math]::Sign([int] '-42')) to guide method-overload resolution to avoid ambiguity.
[1] E.g., the explicit [double] is quietly converted to an [int] in the following statement: & { param([int] $i) $i } ([double] '1.2'). Also, casts to .NET interfaces generally have no effect in PowerShell - except to guide overload resolution in .NET method calls.
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/328027.html
標籤:电源外壳
