Как преобразовать текстовые файлы в папке в файл CSV - PullRequest
0 голосов
/ 15 февраля 2020

Я пытаюсь написать скрипт, чтобы взять кучу текстовых файлов в папке (которые все в одном формате) и вывести их в CSV-файл. Каждый файл имеет одинаковую информацию «заголовка». Мне удалось получить информацию в более удобном для использования формате (без удаления первой и последней строк, которые не нужны), но после этого у меня возникли некоторые проблемы.

Вот начало текстового файла, хотя будет больше, чем просто эти 7 строк, всего будет 36 строк на файл:

TYPE       VOID
DOB        20200131
DATE       20200131
TIME       21:19:42
TERMINAL   3
ORGTERM    2
EMPLOYEE   1234 John Doe

И вот что До сих пор, хотя я знаю, что это не работает:

$currentdir = '.\'
$results = @()
$outputfilename = 'data.csv'

foreach ($req in Get-ChildItem($currentdir)) {

(Get-Content $req)[1..((Get-Content $req).count - 2)] | 
    ForEach-Object {
        $header = $_[0] -split '`t'
        $data = $_[1] -split '`t'
        $results = $header, $data
    }  
}  

Конечный продукт будет выглядеть примерно так:

       A               B            C            D          E            F             G
1     TYPE            DOB          DATE         TIME     TERMINAL     ORGTERM       EMPLOYEE
2     VOID          20200131     20200131     21:19:42      3            2          1234 John Doe
3     AUTHORIZE     20200131     20200131     23:29:22      2                       4678 Jane Doe

Полный образец файла VOID:

BEGIN
TYPE       VOID
DOB        20200131
DATE       20200131
TIME       21:19:42
TERMINAL   3
ORGTERM    2
EMPLOYEE   1234 Jane Doe
TABLE      TBL 101
CHECK      20030
PAYMENT    20029
AUTHAMT    20.68
BATCHAMT   20.68
CARDTYPE   MASTERCARD
CARDMASK   XXXXXXXXXXXXXXXXX
{XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}
EXP        0423
REF        482
STANDALONE YES
PINDEX     1
APPROVEAMT 20.68
LOGTIME    21:07:01
FOHFEATS   10000000000000000000000000000000
TERMCAPS   00000000000000000000000000000000
FOHVERSION 15.1.34.2.97
ACTIONCODE 000
LASTSEND   1580585993
ORIGDATE   20200131
ORIGTIME   21:02:11
ORIGTYPE   AUTHORIZE
ORIGREF    482
ORGREFTIME 21:02:11
TENDER_NUM 12
CRCY       840
VPD        Sequence #: 107
REVID      2
REVNAME    712 Bar
END

Пример файла AUTHORIZE:

BEGIN
TYPE       AUTHORIZE
DOB        20200131
DATE       20200131
TIME       23:29:22
TERMINAL   2
EMPLOYEE   1234 Jane Doe
TABLE      Table 121
CHECK      20045
PAYMENT    20038
AUTHAMT    72.42
BATCHAMT   72.42
CARDTYPE   VISA
CARDMASK   XXXXXXXXXXXXXXXX
{XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}
EXP        0124
REF        485900
STANDALONE YES
PINDEX     1
LOGTIME    23:29:22
FOHFEATS   10000000000000000000000000000000
TERMCAPS   00000000000000000000000000000000
FOHVERSION 15.1.34.2.97
LASTSEND   1580586235
TENDER_NUM 13
CRCY       840
REVID      1
REVNAME    712 Restaurant
COMMERROR  TRUE
END

Пример файла настройки:

BEGIN
TYPE       ADJUST
DOB        20200131
DATE       20200131
TIME       22:18:27
TERMINAL   8
ORGTERM    8
EMPLOYEE   789 Judy Garland
TABLE      BAR GUEST
CHECK      80161
PAYMENT    80036
BATCHAMT   30.43
BATCHTIP   6
CARDTYPE   MASTERCARD
CARDMASK   XXXXXXXXXXXX8699
{XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}
EXP        0323
REF        1504602
STANDALONE YES
PINDEX     1
LOGTIME    22:18:27
FOHFEATS   10000000000000000000000000000000
TERMCAPS   00000000000000000000000000000000
FOHVERSION 15.1.34.2.97
LASTSEND   1580638928
TENDER_NUM 12
CRCY       840
REVID      4
REVNAME    712 Second Bar
END

Ответы [ 3 ]

1 голос
/ 16 февраля 2020

вот один из способов объединения этих текстовых файлов в CSV. Предполагается, что файлы находятся в указанном c dir и могут быть загружены путем сопоставления имен ИЛИ путем простого захвата всех файлов.

что он делает ...

  • устанавливает исходный каталог
  • устанавливает фильтр файлов
  • захватывает все соответствующие файлы
  • перебирает список файлов
  • загружает каждый файл в $ Var
  • использует способ, которым Po Sh обрабатывает коллекцию на левой стороне совпадения
    , которое дает вам соответствующий элемент, а не обычный [bool].
  • создает PSCustomObject
    . Он делает это, сопоставляя строку с целевым словом, получая 1-й элемент в возвращенном массиве, заменяет ненужную часть строки ничем и, наконец, присваивает это значение желаемое свойство.
    это довольно неэффективно, но я не могу придумать лучшего способа. [ blu sh]
  • отправляет PSCO в коллекцию $Results
  • показывает, что в $Results на экране
  • экспорт $Results в файл CSV

вот код ...

$SourceDir = $env:TEMP
$Filter = 'harlan_*.txt'

$FileList = Get-ChildItem -LiteralPath $SourceDir -Filter $Filter -File

$Results = foreach ($FL_Item in $FileList)
    {
    $Lines = Get-Content -LiteralPath $FL_Item.FullName
    [PSCustomObject]@{
        Type = ($Lines -match '^type')[0] -replace '^type\s{1,}'
        DOB = ($Lines -match '^dob')[0] -replace '^dob\s{1,}'
        Date = ($Lines -match '^date')[0] -replace '^date\s{1,}'
        Time = ($Lines -match '^time')[0] -replace '^time\s{1,}'
        Terminal = ($Lines -match '^terminal')[0] -replace '^terminal\s{1,}'
        OrgTerm = ($Lines -match '^orgterm')[0] -replace '^orgterm\s{1,}'
        Employee = ($Lines -match '^employee')[0] -replace '^employee\s{1,}'
        }
    }

# show on screen   
$Results

# save to CSV
$Results |
    Export-Csv -LiteralPath "$SourceDir\Harlan_-_MergedFiles.csv" -NoTypeInformation

отображение на экране ...

Type     : ADJUST
DOB      : 20200131
Date     : 20200131
Time     : 22:18:27
Terminal : 8
OrgTerm  : 8
Employee : 789 Judy Garland

Type     : AUTHORIZE
DOB      : 20200131
Date     : 20200131
Time     : 23:29:22
Terminal : 2
OrgTerm  : 
Employee : 1234 Jane Doe

Type     : VOID
DOB      : 20200131
Date     : 20200131
Time     : 21:19:42
Terminal : 3
OrgTerm  : 2
Employee : 1234 Jane Doe

содержимое CSV-файл ...

"Type","DOB","Date","Time","Terminal","OrgTerm","Employee"
"ADJUST","20200131","20200131","22:18:27","8","8","789 Judy Garland"
"AUTHORIZE","20200131","20200131","23:29:22","2","","1234 Jane Doe"
"VOID","20200131","20200131","21:19:42","3","2","1234 Jane Doe"
1 голос
/ 16 февраля 2020

Чтобы захватить все поля в файлах без жесткого кодирования заголовков и объединить их в файл CSV, следующий код должен это сделать.
Замедление состоит в том, что в каждом файле есть одна строка, в которой нет заголовка , это просто строка {XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}.

Я предполагаю, что это должен быть номер карты, поэтому я вручную вставляю туда заголовок CARDNUMBER. Если это что-то еще, пожалуйста, измените это в коде.

$files = Get-ChildItem -Path 'D:\Test' -File

$result = foreach($file in $files) {
    $obj = [PsCustomObject]@{}
    Get-Content -Path $file.FullName | Where-Object { $_ -notmatch '^(BEGIN|END)$' } | ForEach-Object {
        # There is a line without 'header' name. Is this the card number?
        if ($_ -like '{*}') {
            $name = 'CARDNUMBER'  # <-- add your own preferred header name here
            $value = $_
        }
        else {
            $name,$value = $_ -split '\s+', 2
        }
        $obj | Add-Member -MemberType NoteProperty -Name $name -Value $value
    }
    # output the object for this file to be colected in the $result variable
    $obj
}

# output on screen
$result

#output  to CSV file
$result | Export-Csv -Path 'D:\output.csv' -NoTypeInformation

Вам необходимо установить пути для Get-ChildItem и Export-CSV, чтобы они соответствовали вашей собственной ситуации, конечно же

0 голосов
/ 16 февраля 2020

Если я правильно читаю, у вас есть несколько файлов, в каждом из которых есть одна запись данных, разделенных между удачно расположенными словами «НАЧАЛО» и «КОНЕЦ». Вы хотите, чтобы каждый файл был переведен в один файл CSV?

Я думаю, что приготовил что-то стоящее. Хотя я уверен, что он не идеален.

$Select   = 'TYPE','DOB','DATE','TIME','TERMINAL','ORGTERM','EMPLOYEE'
ForEach( $InputFile in (Get-ChildItem $CurrentDirectory) )
{
    $OutputFile = $InputFile.BaseName + '.csv'
    $Table    = Get-Content $InputFile
    $TempHash = [Ordered]@{}

    ForEach( $Column in $Table )
    {
        If( $Column -notmatch '(^BEGIN$|^END$)' )
        {
            $TempArr = $Column.Split( ' ', 2, [System.StringSplitOptions]::RemoveEmptyEntries ) | ForEach{$_.Trim()}

            If( $Select -contains $TempArr[0] )
            {
                $TempHash.Add($TempArr[0], $TempArr[1] )
            }
        }
    }

    #Now $TempHash should have enough to create the object and export to CSV
    [PSCustomObject]$TempHash | Export-Csv -Path $OutputFile -NoTypeInformation 
}

Несколько моментов:

  • Я игнорирую строки НАЧАЛО И КОНЕЦ
  • Я манипулирую затем каждая строка в массиве, который по большей части должен состоять из 2 элементов.
  • Если первый элемент [0] находится в коллекции файлов, которую вы ищете, я добавлю в качестве пары ключ / значение для га sh. В противном случае ничего не делать.
  • После обработки строк Преобразовать объект в PSCustomObject и экспортировать в файл CSV.
  • Я протестировал его только на одном файле, созданном по вашему вопросу. Я обернул внешний l oop как псевдокод.

Это работает, но вывод выглядит немного изменчиво, как числа, являющиеся строками и тому подобное. Тем не менее, я считаю, что в качестве версии у нас есть кое-что для работы.

Если вы неправильно прочитали свой комментарий и вам нужен один выходной CSV-файл, корректировка состоит в том, чтобы просто объявить имя файла перед l oop и используйте параметр append в командлете Export-CSV. Смотрите ниже, хотя я больше не проверял это:

$OutputFile = 'YourOutput.csv'
$Select   = 'TYPE','DOB','DATE','TIME','TERMINAL','ORGTERM','EMPLOYEE'

ForEach( $InputFile in (Get-ChildItem $CurrentDirectory) )
{
    $Table    = Get-Content $InputFile
    $TempHash = [Ordered]@{}

    ForEach( $Column in $Table )
    {
        If( $Column -notmatch '(^BEGIN$|^END$)' )
        {
            $TempArr = $Column.Split( ' ', 2, [System.StringSplitOptions]::RemoveEmptyEntries ) | ForEach{$_.Trim()}

            If( $Select -contains $TempArr[0] )
            {
                $TempHash.Add($TempArr[0], $TempArr[1] )
            }
        }
    }

    #Now $TempHash should have enough to create the object and export to CSV
    [PSCustomObject]$TempHash | Export-Csv -Path $OutputFile -NoTypeInformation -Append

}

Извините за имена переменных, которые, очевидно, могли бы использовать рефакторинг ...

Дайте мне знать, что вы думаете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...