2010-09-17 81 views
2

我有一个文本文件,其中包含几行,每一行都是逗号分隔的字符串。每一行的格式为:使用powershell解析逗号分隔文件

<Name, Value, Bitness, OSType>

BitnessOSType是可选的。

例如该文件可以是这样的:

Name1, Value1, X64, Windows7 
Name2, Value2, X86, XP 
Name3, Value3, X64, XP 
Name4, Value3, , Windows7 
Name4, Value3, X64 /*Note that no comma follows X64 */ 
.... 
.... 

欲每一行解析成4个变量和在其上执行一些操作。这是我使用的PowerShell脚本..但是,我想知道是否可以在PowerShell中使用正则表达式来执行此操作。你能否提供这样的示例代码?请注意,每行中的第3个和第4个值可以选择为空。

+5

请不要使用正则表达式解析CSV。 :)这是对人类的犯罪。 – Josh 2010-09-17 07:08:48

回答

3

使用Import-Csv能为您做所有这些(而且更可靠)吗?

+4

如果你已经有一行CSV文件,你可以将它传递给'ConvertFrom-Csv'来将它变成一个对象。这两个命令都可以让你指定一个自定义分隔符。 – Josh 2010-09-17 07:06:59

3

正如Tim所建议的那样,您可以使用Import-Csv。不同之处在于Import-Csv从文件读取。

@" 
Name1, Value1, X64, Windows7 
Name2, Value2, X86, XP 
Name3, Value3, X64, XP 
Name4, Value3, , Windows7 
Name4, Value3, X64 /*Note that no comma follows X64 */ 
"@ | ConvertFrom-Csv -header var, val, bitness, ostype 

# Result 

var val bitness         ostype 
--- --- -------         ------ 
Name1 Value1 X64          Windows7 
Name2 Value2 X86          XP  
Name3 Value3 X64          XP  
Name4 Value3           Windows7 
Name4 Value3 X64 /*Note that no comma follows X64 */   
6

您可以用Import-Csv cmdlet的-Header参数指定导入的文件的文件替代的列标题行:

Import-Csv .\test.txt -Header Col1,Col2,Bitness,OSType 
0

比糖蜜慢,但经历二十年拼凑十几个或更多后部分解决方案,我决定明确解决它。当然,随着时间的推移,各种解析器库现在都可用。


function SplitDelim($Line, $Delim=",", $Default=$Null, $Size=$Null) { 

    # 4956968,"""Visible,"" 4D ""Human"" Torso Anatomy Kit (4-5/8)",FDV-26051,"" ,"",,,,,,a 
    # "4956968,"""Visible,"" 4D ""Human"" Torso Anatomy Kit (4-5/8)",FDV-26051,"" ,"",,,,,,a 
    # ,4956968,"""Visible,"" 4D ""Human"" Torso Anatomy Kit (4-5/8)",FDV-26051,"" ,"",,,,,,a 

    $Field = "" 
    $Fields = @() 
    $Quotes = 0 
    $State = 'INF' # INFIELD, INQFIELD, NOFIELD 
    $NextState = $Null 

    for ($i=0; $i -lt $Line.length; $i++) { 
     $Char = $Line.substring($i,1) 

     if($State -eq 'NOF') { 

      # NOF and Char is Quote 
      # NextState becomes INQ 
      if ($Char -eq '"') { 
       $NextState = 'INQ' 
      } 

      # NOF and Char is Delim 
      # NextState becomes NOF 
      elseif ($Char -eq $Delim) { 
       $NextState = 'NOF' 
       $Char = $Null 
      } 

      # NOF and Char is not Delim, Quote or space 
      # NextState becomes INF 
      elseif ($Char -ne " ") { 
       $NextState = 'INF' 
      } 

     } elseif ($State -eq 'INF') { 

      # INF and Char is Quote 
      # Error 
      if ($Char -eq '"') { 
       return $Null} 

      # INF and Char is Delim 
      # NextState Becomes NOF 
      elseif ($Char -eq $Delim) { 
       $NextState = 'NOF' 
       $Char = $Null 
      } 

     } elseif ($State -eq 'INQ') { 

      # INQ and Char is Delim and consecutive Quotes mod 2 is 0 
      # NextState is NOF 
      if ($Char -eq $Delim -and $Quotes % 2 -eq 0) { 
       $NextState = 'NOF' 
       $Char = $Null 
      } 
     } 

     # Track consecutive quote for purposes of mod 2 logic 
     if ($Char -eq '"') { 
      $Quotes++ 
     } elseif ($NextState -eq 'INQ') { 
      $Quotes = 0 
     } 

     # Normal duty 
     if ($State -ne 'NOF' -or $NextState -ne 'NOF') { 
      $Field += $Char 
     } 

     # Push to $Fields and clear 
     if ($NextState -eq 'NOF') { 
      $Fields += (IfBlank $Field $Default) 
      $Field = '' 
     } 

     if ($NextState) { 
      $State = $NextState 
      $NextState = $Null 
     } 
    } 

    $Fields += (IfNull $Field $Default) 

    while ($Size -and $Fields.count -lt $Size) { 
     $Fields += $Default 
    } 

    return $Fields 
}