Пустой файл CSV создается при чтении 1 строки данных, разделенных табуляцией, и экспорте в разделитель «+» - PullRequest
0 голосов
/ 25 марта 2019

Цель сценария (PowerShell) состоит в том, чтобы взять текстовый файл с разделителями табуляции, удалить строку заголовка, изменить разделитель на «+», добавить пользовательскую запись заголовка и добавить итоговую (нижний колонтитул) строку в нижней частифайл с подсчетом количества записей данных.Наконец, расширение файла необходимо заменить на порядковый номер.

Когда необработанный файл содержит более 1 строки, результат соответствует требуемому, но когда только одна строка (заголовок плюс 1 строка данных), выводфайл пуст.

$dir = "C:\Temp\Data"
$file = "rand1"

$sequencefile = "C:\temp\Sequential\DoNotDeleteSequence.txt"

$sequencenumber = (Get-Content $sequencefile)
$newsequencenumber = ($sequencenumber/1) + 1

Clear-Content $sequencefile
Add-Content $sequencefile $newsequencenumber

$backslash = "\"
$ext = ".txt"
$filename = $dir + $backslash + $file + $ext
$text = "TRAILER = "
$dateText = Get-Date -Format d
$Header1 = "HEADER="
$Header2 = "+PSTG"
$HeaderText = $Header1 + $dateText + $Header2

$tempfile1 = "step1" 
$tempfile2 = "step2" 
$tempfile3 = "step3" 
$tempfile4 = "step4" 

$temppstg = "PSTG_NCDLPSTG."

$stepfile1 = $dir + $backslash + $tempfile1 + $ext
$stepfile2 = $dir + $backslash + $tempfile2 + $ext
$stepfile3 = $dir + $backslash + $tempfile3 + $ext
$stepfile4 = $dir + $backslash + $tempfile4 + $ext

$pstgfile = $dir + $backslash + $temppstg + $newsequencenumber

(Get-Content $filename).Replace("+", '') | Set-Content $stepfile1
(Get-Content $stepfile1) | select -Skip 1 | Set-Content $stepfile2
Import-Csv $stepfile2 -Delimiter "`t" | Export-Csv $stepfile3 -Delimiter "+" -NoTypeInformation
Set-Content $stepfile4 $HeaderText
(Get-Content $stepfile3).Replace("""", '') | Add-Content $stepfile4
$records = Import-Csv $stepfile4 | Measure-Object | Select-Object -Expand Count

$textToWrite = $text + $records

Add-Content $stepfile4 $textToWrite

Rename-Item $stepfile4 $pstgfile

Я создал 2 тестовых необработанных файла (с разделителями табуляции).

C:\Temp\Data\rand1.txt, содержащих

Header  Row
Record1 Data1

C:\Temp\Data\rand2.txt, содержащих

Header  Row
Record1 Data1
Record2 Data2

Когда через код передается rand2.txt, результат будет

HEADER=25/03/2019+PSTG
Record1+Data1
Record2+Data2
TRAILER = 2

Когда обрабатывается rand1.txt, результат равен

HEADER=25/03/2019+PSTG
TRAILER = 0

1 Ответ

0 голосов
/ 26 марта 2019

Следующие два шага обработки вызывают поведение, которое вы наблюдали:

(Get-Content $stepfile1) | select -Skip 1 | Set-Content $stepfile2
Import-Csv $stepfile2 -Delimiter "`t" | Export-Csv $stepfile3 -Delimiter "+" -NoTypeInformation

Чтобы понять, что происходит, вам просто нужно взглянуть на отдельные этапы обработки. Я показываю ввод и вывод для файлов rand1.txt (слева) и rand2.txt (справа) рядом, чтобы проиллюстрировать, что происходит.

  1. (Get-Content $stepfile1) | select -Skip 1 | Set-Content $stepfile2

    Введите:

    Header   Row                  Header   Row
    Record1  Data1                Record1  Data1
                                  Record2  Data2
    

    Выход:

    Record1  Data1                Record1  Data1
                                  Record2  Data2
    

    Этот шаг удаляет строку заголовка, оставляя вам одну строку для rand1.txt, но две строки для rand2.txt. Это само по себе не является основной причиной проблемы, которую вы наблюдали, но оно готовит почву для настоящего виновника.

  2. Import-Csv $stepfile2 -Delimiter "`t" | Export-Csv $stepfile3 -Delimiter "+" -NoTypeInformation

    Введите:

    Record1  Data1                Record1  Data1
                                  Record2  Data2
    

    Выход:

                                  Record1+Data1
                                  Record2+Data2
    

    Этот шаг оставляет вас без вывода для rand1.txt, но обе записи для rand2.txt, из-за того, как Import-Csv и Export-Csv работают.

    Import-Csv преобразует строки файла с разделителями в пользовательские объекты, а поля каждой строки в свойства этих объектов, взяв имена этих свойств из первой строки входного файла.

    Export-Csv выполняет полярную противоположность своего командного элемента: он преобразует список пользовательских объектов в строки данных, а значения свойств объекта - в поля строк данных. Имена свойств первого объекта в списке определяют, какие свойства экспортируются, а также формируют строку заголовка выходного файла.

    Поскольку rand1.txt имеет только одну строку (т. Е. Только строку заголовка), при импорте никакие объекты не создаются из-за отсутствия данных, следовательно, нет данных для экспорта обратно в файл. rand2.txt с другой стороны имеет две строки, поэтому при импорте вы получаете один объект со следующей структурой (в нотации JSON):

    {
      "Record1": "Record2",
      "Data1": "Data2"
    }
    

    , который затем преобразуется обратно в строку заголовка Record1+Data1 и строку данных Record2+Data2.

Последующие шаги только добавляют новую строку заголовка к промежуточным текстовым файлам, которые вы создали. Если бы вы не удалили заголовок перед использованием Import-Csv или вообще не использовали командлеты *-Csv, эта проблема не возникла бы.

С учетом вышесказанного вся ваша обработка слишком сложна . Вы можете достичь желаемого результата только с помощью следующих строк (некоторые определения переменных для краткости опущены):

$filename = Join-Path $dir "${file}${ext}"

$records = (Get-Content $filename).Replace('+', '').Replace("`t", '+') |
           Select-Object -Skip 1

$newsequencenumber = [int](Get-Content $sequencefile) + 1
$pstgfile = Join-Path $dir "PSTG_NCDLPSTG.${newsequencenumber}"

"HEADER=$(Get-Date -Format d)+PSTG" | Set-Content $ptsgfile
$records | Add-Content $ptsgfile
"TRAILER = $($records.Count)" | Add-Content $ptsgfile
...