我需要对基于区域性格式化的文本文件中的数字进行一些数学运算,所以我可以得到1234.56,或者我可以得到1.234,56,甚至1234,56。我原本想通过了解当前的文化
$culture = (Get-Culture).Name
然后将所有数字转换为en-US格式,进行数学运算,然后转换回原始格式。然而,像这样简单的事情是行不通的。
$useCulture = New-Object System.Globalization.CultureInfo("en-US")
$value1 = "1,234.56"
$value2 = "1234,56"
[double]$value1 = $value1.ToString("f", $useCulture)
[double]$value2 = $value2.ToString("f", $useCulture)
$value1
$value2
我希望这两个值都能返回1234.56,但第二个值返回为123456,所以很明显我不理解ToString是如何工作的。我的猜测是,它假设它所拥有的是美国格式,因为这就是我的机器的配置,然后它试图转换为相同的东西,而在$value2上,它只是假设数千分隔符放错了地方?在任何情况下,我将如何从任意格式转换为指定格式,以便确保总和正确,然后再转换回原始的任意格式?或者,我是不是完全错过了什么,有更好的方法来解决这个问题?此外,如果可能的话,我希望能够使用PS 2.0做到这一点,因为我不能依赖于目标机器升级到新版本。
因此,如果总体结果是你想要的东西只有数字,最多只有一个小数点,我会尝试以下方法:
- 将任何非小数点替换为点
- 去掉最后一个点以外的所有点,我们将其视为小数点
以下是一个适用于一些测试用例的示例函数,但我在测试中肯定没有详尽无遗:
function ConvertTo-Number {
param(
[Parameter(
Mandatory=$true)]
[System.String]
$String
)
if($String -notmatch 'D'){
return [int]$String
} else {
$ConvertedValue = ($String -replace 'D','.') -match '^(?<int>.*?)(?<dec>[d]*)$'
$ConvertedValue = $matches["int"] -replace 'D',''
if($matches["dec"]){
$ConvertedValue+=".$($matches["dec"])"
}
return [double]$ConvertedValue
}
}
如果可能的话,您可能需要先清理输入字符串,例如,在进行其他操作之前删除空格。
您可以执行以下操作:
# Your input value
$value = '1 234,56'
# Determine culture of input format
if ($value -match '.dd$') {
$culture = [cultureinfo]::GetCultureInfo('en-us')
} elseif ($value -match '.ddd') {
$culture = [cultureinfo]::GetCultureInfo('de-de')
} elseif ($value -match ' ddd|,dd$') {
$culture = [cultureinfo]::GetCultureInfo('fr-fr')
}
# Parse input value into a double and perform math, e.g. value * 27.2
$newvalue = [double]::Parse($value,$culture) * 27.2
# Convert computed value back to original culture
$newvalue.ToString('n2',$culture)