Преобразование текстового файла Powershell в файл CSV построчно

Задача: Преобразовать текст, записанный с экрана, в CSV для импорта в Excel. Среда: Windows 11, Блокнот, Powershell ISE, Powershell v5.1. Текстовый формат: одна строка на запись с окончаниями CR LF, проверено с помощью Scite. Текст для преобразования имеет повторяющийся шаблон из 7 строк, заканчивающийся строкой, содержащей уникальный слово, за которым следуют пустые строки (CR LF). Количество пустых строк непоследовательно.

Мое решение: Прочтите каждую строчку. Если строка содержит уникальное слово, добавьте строку в файл, сохраняя CR LF. Если строка пуста, ничего не делайте. Если строка не содержит уникального слова, преобразуйте CR LF в запятую и добавьте в выходной файл. Пример входного файла:

28
--
123.123.123.123 - fgh1
00:00:00:00:00:00
someword
 anotherword
INDEX word: 11


29
--
123.123.123.124 - fgh1
00:00:00:00:00:00
someword "INDEX
 anotherword
INDEX word: 11

Желаемый формат выходного файла:

28,--,123.123.123.123 - fgh1,00:00:00:00:00:00,someword, anotherword,INDEX word: 11
29,--,123.123.123.124 - fgh1,00:00:00:00:00:00,someword, anotherword,INDEX word: 11

Этот PS-скрипт распознает уникальные слова:

foreach($line in [System.IO.File]::ReadLines(C:\InFile.txt))
{
 If ($line -match "INDEX" {Write-Host "Line contains INDEX"}
 ElseIf ($line -notmatch "INDEX") (Write-Host "Line does not contain INDEX"}
 }

Однако я не могу заставить следующий сценарий заменить CR LF запятыми и создать желаемый формат файла. Скрипт просто записывает исходный формат файла в OutFile.

foreach($line in [System.IO.File]::ReadLines(C:\InFile.txt))
{
 If ($line -match "INDEX" {Out-File -append -FilePath C:\OutFile.txt -inputobject $line}
 ElseIf ($line -notmatch "INDEX") (Out-File -append -filepath C:\OutFile.txt -inputobject ($line -replace '\r?\n',',')}
 }

Обратите внимание, почему я использую метод [System.IO.File]::ReadLines: мне не удалось получить правильные уникальные совпадения слов, используя:

$FilePath = "C:Infile.txt"
$FileContents = Get-Content -Path $FilePath -Raw | Out-String #Tried with or without "Out-String"
ForEach ($Line in $FileContents){
If ($Line -match -match "INDEX" {Write-Host "Line contains INDEX"}
ElseIf ($line -notmatch "INDEX") (Write-Host "Line does not contain INDEX"}
 }

Если вы просто опустите переключатель -Raw, вы получите массив строк из Get-Content.

iRon 07.03.2024 21:03

Спасибо, мои исследования привели меня к мысли, что добавление -Raw на самом деле возвращает строки, а не объекты. Код Get-Content теперь обнаруживает строку «INDEX». У меня все еще есть замена CR LF с запятой, чтобы начать работать.

RASmith 07.03.2024 21:25
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
115
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

это может помочь, но, наконец, вам нужно определить строку заголовка:

$content = (gc C:\inFile.txt | ?{$_}) 
$list = [System.Collections.Generic.List[string]]::New()
$newContent = @(
    foreach ($line in $content){
        $list.add($line)
        If ($line -match '^index'){
            $list -join ','
            $list = [System.Collections.Generic.List[string]]::New()
        }
    }
)
$newContent | set-content .\myCsv.csv

Спасибо за это предложение. К сожалению, для меня это слишком кратко.

RASmith 07.03.2024 21:17
Ответ принят как подходящий

Вы можете проанализировать данные из такого файла, как показано ниже:

$fileIn  = 'C:\inFile.txt'
$fileOut = 'C:\OutFile.txt'
$headers = (1..7 | ForEach-Object { "Column$_" } ) -join ','     # create a header line for the csv file

# read the file as single multiline string and parse the data
$data = (Get-Content -Path $fileIn -Raw) -split '(\r?\n){2,}' |  # split the text on the multiple Newlines
Where-Object { $_ -match '\S' } |                                # ignore empty or whitespace-only parts
ForEach-Object { ($_ -split '\r?\n') -join ',' }                 # split each part on Newline and join the elements with a comma

# write the headers to csv file, then the data
$headers | Set-Content -Path $fileOut
$data | Add-Content -Path $fileOut

P.S. Ваш пример не дает мне понять, почему вам следует искать слово INDEX, поскольку оно есть в обоих блоках данных.

Спасибо за решение и комментарии. Это решение работает. Мне было неясно, нужна ли строка заголовка. Строка INDEX является последней строкой в ​​каждой записи. Я обрабатываю некоторые записи, которые не имеют регулярной длины, и единственной общей чертой является последняя строка в каждой записи. Ранее я конвертировал их с помощью BAT, VBS или даже C, разделяя их последней строкой каждой записи. Я надеялся, что PS будет проще. Еще раз спасибо.

RASmith 08.03.2024 20:40

Другие вопросы по теме