Задача: Преобразовать текст, записанный с экрана, в 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 теперь обнаруживает строку «INDEX». У меня все еще есть замена CR LF с запятой, чтобы начать работать.





это может помочь, но, наконец, вам нужно определить строку заголовка:
$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
Спасибо за это предложение. К сожалению, для меня это слишком кратко.
Вы можете проанализировать данные из такого файла, как показано ниже:
$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 будет проще. Еще раз спасибо.
Если вы просто опустите переключатель
-Raw, вы получите массив строк изGet-Content.