Полезный ответ Nas работает, но это операция O (m * n); то есть при наличии m абзацев для вывода в заданном порядке и n входных абзацев требуется выполнить m * n операций; если все входные абзацы должны быть выведены (в установленном порядке), т. е. если m равно n, усилие равно квадратичному .
Следующее решение PSv4 + будет масштабироваться лучше, поскольку для него требуется только линейное , а не квадратичное усилие:
# The tokens prescribing the sort order, which may come from
# another file read with Get-Content, for instance.
$tokensToSortBy = '18C', '25C', '21C'
# Create a hashtable that indexes the input file's paragraphs by the sort
# token embedded in each.
((Get-Content -Raw file.txt) -split '\r?\n\r?\n' -replace '\r?\n$').ForEach({
$htParagraphsBySortToken[$_ -replace '(?s).* (\d+C)$(?:\r?\n)?', '$1'] = $_
})
# Loop over the tokens prescribing the sort order, and retrieve the
# corresponding paragraph, then reassemble the paragraphs into a single,
# multi-line string with -join
$tokensToSortBy.ForEach({ $htParagraphsBySortToken[$_] }) -join [Environment]::NewLine * 2
(Get-Content -Raw file.txt)
считывает входной файл в память целиком как одну многострочную строку.
-split '\r?\n\r?\n'
разбивает многострочную строку на массив абзацев (блоки строк, разделенных пустой строкой), а -replace '\r?\n$'
удаляет завершающий символ новой строки, если таковой имеется, из абзаца в самом конце файла.
- Regex
\r?\n
совпадает как с CRLF в стиле Windows, так и с новыми строками LF только для Unix.
$_ -replace '(?s).* (\d+C)$(?:\r?\n)?', '$1'
извлекает маркер сортировки (например, 25C
) из каждого абзаца, который становится ключом хеш-таблицы.
$_
представляет входной абзац под рукой.
-replace '...', '...'
выполняет замену строки на основе регулярного выражения.
-join [Environment]::NewLine * 2
собирает отсортированные абзацы в одну многострочную строку с абзацами, разделенными пустой строкой.
[Environment]::NewLine
- соответствующая платформе последовательность новой строки; альтернативно вы можете жестко закодировать новые строки как "`r`n"
(CRLF) или "`n"
(LF).
Вы можете отправить вывод в новый файл, добавив что-то вроде
... | Set-Content sortedFile.txt
до последнего оператора (что делает файл «ANSI» кодированным в Windows PowerShell и UTF-8 в PowerShell Core по умолчанию; при необходимости используйте -Encoding
.