Разбор файла через запятую с использованием powershell - PullRequest
2 голосов
/ 17 сентября 2010

У меня есть текстовый файл, который содержит несколько строк, каждая из которых представляет собой строку, разделенную запятыми. Формат каждой строки:

<Name, Value, Bitness, OSType>

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 */
....
....

Я хочу разобрать каждую строку на 4 переменные и выполнить с ней некоторую операцию. Это скрипт PowerShell, который я использую ..

Get-Content $inputFile | ForEach-Object {
    $Line = $_;

    $_var = "";
    $_val = "";
    $_bitness = "";
    $_ostype = "";

    $envVarArr = $Line.Split(",");
    For($i=0; $i -lt $envVarArr.Length; $i++) {
        Switch ($i) {
            0 {$_var = $envVarArr[$i].Trim();}
            1 {$_val = $envVarArr[$i].Trim();}
            2 {$_bitness = $envVarArr[$i].Trim();}
            3 {$_ostype = $envVarArr[$i].Trim();}
        }                                    
    }
    //perform some operation using the 4 temporary variables
}

Однако я хотел знать, возможно ли это сделать с помощью регулярных выражений в PowerShell. Не могли бы вы предоставить пример кода для этого? Обратите внимание, что 3-е и 4-е значения в каждой строке могут быть необязательно пустыми.

Ответы [ 4 ]

6 голосов
/ 17 сентября 2010

Можно указать альтернативную строку заголовка столбца для импортируемого файла с помощью параметра -Header командлета Import-Csv:

Import-Csv .\test.txt -Header Col1,Col2,Bitness,OSType
3 голосов
/ 17 сентября 2010

Как подсказывает Тим, вы можете использовать команду 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 */         
3 голосов
/ 17 сентября 2010

Не лучше ли использовать Import-Csv, который сделает все это (и более надежно) для вас?

0 голосов
/ 30 января 2013

Медленнее, чем патока, но, потратив 20 лет на то, чтобы собрать дюжину или более частичных решений, я решил заняться этим окончательно.Конечно, со временем все виды библиотек синтаксического анализатора теперь доступны.


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
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...