powershell - 如何在PowerShell中将字符串转换为double?

标签 powershell type-conversion

我在 PowerShell 中有一个脚本,用于从 CSV 导入数据。我收到一个错误

无法将值“Journal Amount”转换为类型“System.Double”。错误:“输入字符串的格式不正确。”
在 C:\TestPowerShell\TestPowerShell1.ps1:98 字符:1
+ $JournalAmount = [double] $_.PSObject.Properties['Journal Amount'].Va ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [], RuntimeException
+ FullQualifiedErrorId : InvalidCastFromStringToDoubleOrSingle

这是我的代码:

Get-Content "config.txt" | foreach-object -begin {$h=@{}} -process { $k = [regex]::split($_,'='); if(($k[0].CompareTo("") -ne 0) -and ($k[0].StartsWith("[") -ne $True)) { $h.Add($k[0], $k[1]) } }

$FileBrowserInitialDir = $h.FileBrowserInitialDir
$Header = 'Terminal','Company','Journal Account Code','Project','Task','Line of Business','Date','Journal Amount','Report Entry Vendor Description'

$TIDataFilePath = $h.TIDataFilePath
$TIDataFileBaseName = $h.TIDataFileBaseName

$TIScreenID = $h.TIScreenID
$TIControlFile = $h.TIControlFile
$TIErrLog = $h.TIErrLog

$ResultsFilePath = $h.ResultsFilePath
$ResultsFileBaseName = $h.ResultsFileBaseName

$dt = Get-Date -Format "MMddyyyyHHmmss"
$TIDataFile = "$($TIDataFileBaseName)$($dt).txt"
$ResultsFile = "$($ResultsFileBaseName)$($dt).txt"

Add-Type -AssemblyName System.Windows.Forms
$FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{ 
    InitialDirectory = $FileBrowserInitialDir
    Filter = 'CSV (*.csv)|*.csv'
    Title = "Select Expense csv file"
}
$null = $FileBrowser.ShowDialog()

if($FileBrowser.FileName -eq ""){
    exit
}


 $EXPENSECSV = Import-CSV $FileBrowser.FileName -Header $Header
 New-Item -path $TIDataFilePath -name $TIDataFile -type "file"
 $EXPENSECSV |foreach-object{    

$Terminal =  $_.PSObject.Properties['Terminal'].Value
$Terminal = $Terminal.Insert(0,'0')

$CompanyTemp =  $_.PSObject.Properties['Company'].Value
$CompanyTemp = $CompanyTemp.Insert(0,'0')
#$Company= [String]::Concat($_.Terminal,$CompanyTemp) 
$Company= [String]::Concat($Terminal,$CompanyTemp) 
$LineofB =  $_.PSObject.Properties['Line of Business'].Value
#$JournalAmount = [double] $_.PSObject.Properties["Journal Amount"].Value
 $LineofB = $LineofB.Insert(0,'0')

 $Account = $_.PSObject.Properties['Journal Account Code'].Value
$Sub = $LineofB

$TranDateStr =  $_.PSObject.Properties['Date'].Value
$JournalAmount = [double] $_.PSObject.Properties['Journal Amount'].Value
$Description =  $_.PSObject.Properties['Report Entry Vendor Description'].Value

    $row = ""
    $row +=  "`"Level1`","
    $row +=  "`"$($Company)`","
    $row +=  "`"$($Account)`","
    $row +=  "`"$($Sub)`","
    $row +=  "`"$($TranDateStr)`","


    # Convert Concur Amount to Credit/Debit Amount
    # Postive Amount  --> Debit Amount
    # Negative Amount --> Credit Amount
    if($JournalAmount -lt 0){
        $JournalAmount*= -1
        $row += "`"$($JournalAmount)`","   #Credit Amount
        $row += "`"`","             #Debit Amount
    }
    else {
        $row += "`"`","             #Credit Amount
        $row += "`"$($JournalAmount)`","   #Debit Amount
    }

    $row += "`"$($Description)`""

   Add-Content -Path "$($TIDataFilePath)$($TIDataFile)" -Value $row
 }

 #Results
 New-Item -path $ResultsFilePath -name $ResultsFile -type "file"

 $ResultsStr =   "----------------------------------------------------------------------------------`n"
$ResultsStr +=  "                             Concur to Dynamics SL                                   `n"
$ResultsStr +=  "----------------------------------------------------------------------------------`n"
$ResultsStr +=  "Copy and paste the following into the Transaction Import screen.`n"
$ResultsStr += "Line 1: Data File Name`n"
$ResultsStr += "Line 2: Screen ID`n"
$ResultsStr += "Line 3: Control File Name`n"
$ResultsStr += "Line 4: Output Log File`n`n`n"
$ResultsStr += "$($TIDataFilePath)$($TIDataFile)`n"
$ResultsStr += "$($TIScreenID)`n"
$ResultsStr += "$($TIControlFile)`n"
$ResultsStr += "$($TIErrLog)"


 Add-Content -path "$($ResultsFilePath)$($ResultsFile)" -value $ResultsStr

Start-Process "$($ResultsFilePath)$($ResultsFile)"

最佳答案

回答问题:

  • 将字符串转换到 [double] - 正如你自己尝试过的 - 确实有效 ,但前提是字符串被识别为(浮点)数字。
  • 警告 : 自 PowerShell 的强制转换是文化不变的,只有 .被识别为小数点 , 和 ,总是被解释为千组分隔符。
  • 分析文化敏感 , 使用 [double]::Parse($string) 根据当前文化的规则进行解析(如 $PSCulture 所示);通过[cultureinfo]实例作为基于给定文化的规则进行解析的第二个参数(例如,要根据法国文化的规则进行解析,请使用 [double]::Parse($string, [cultureinfo] 'fr-FR') )

  • 如果无法识别字符串值 ,您可以使用以下方法之一来处理这种情况:
  • 使用 try / catch 处理错误;例如,悄悄地默认为 0 :
  • [double] $double = try { $string } catch { 0 }

  • 使用 -as , conditional type conversion operator , 返回指定类型的实例,或者,如果转换失败,则返回 $null :
  • $double = $string -as [double]; if ($null -eq $double) { ... }



  • 至于你试过什么 :
    Mathias R. Jessen指出,您的问题的可能原因是您的 CSV 文件本身确实有一个标题行,但您还通过 -Header 提供了标题。范围。
    这会导致 CSV 文件的标题行被误读为第一个数据行,因此第一个对象由 Import-Csv 返回。然后包含列(标题)名称作为属性值 - 然后导致 [double]强制转换失败,因为您正在有效地执行以下操作:[double] 'Journal Amount'所以:
  • 省略 -Header您的 Import-Csv 中的参数称呼。
  • 作为优化,使用普通的点表示法简化属性值检索;只需使用引号来指定属性名称 Journal Amount ,因为它包含一个空格:
  • Import-CSV $FileBrowser.FileName | # !! No -Header argument
      ForEach-Object {
        # Simpler and more efficient than:
        #   $JournalAmount = [double] $_.PSObject.Properties['Journal Amount'].Value
        $JournalAmount = [double] $_.'Journal Amount'
      }
    # ...
    
    

    关于powershell - 如何在PowerShell中将字符串转换为double?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62156057/

    相关文章:

    Azure CLI DevOps 使用 PowerShell 获取创建项目的 ID

    regex - 使用正则表达式匹配多个更改

    java - 将 Map<String,Object> 转换为 Map<String,String>

    type-conversion - 如何将 Int 转换为十六进制字符串?

    Powershell 远程处理配置文件

    powershell - 为什么为 `get-Help about_*`表达式得到其他结果?

    powershell - PowerShell-每个-重复

    java - 从 json 响应将字符串转换为 android 中的数组

    java - 枚举到字符串的转换

    c - 使用 sys/socket.h 宏时的神秘类型转换警告