Как мне сохранить UNIX LF окончания строк? - PullRequest
1 голос
/ 10 февраля 2020

У меня есть большой (9 ГиБ) файл в кодировке ASCII с разделителями канала с окончанием строки UNIX; 0x0A.

Я хочу сэмплировать первые 100 записей в файл для расследования. Следующее будет производить 100 записей (1 запись заголовка и 99 записей данных). Тем не менее, он меняет окончания строк в стиле DOS / Winodws; CRLF, 0x0D0A.

Get-Content -Path .\wellmed_hce_elig_20191223.txt |
    Select-Object -first 100 |
    Out-File -FilePath .\elig.txt -Encoding ascii

Я знаю о iconv, recode и dos2 unix. Эти программы не в моей системе и не могут быть установлены. Я искал и нашел несколько мест, как добраться до CRLF. Я не нашел ничего при получении или сохранении LF.

Как создать файл с окончаниями строки LF вместо CRLF?

Ответы [ 2 ]

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

В дополнение к полезный ответ Тео с оптимизацией производительности на основе мало используемого параметра -ReadCount:

Set-Content -NoNewLine -Encoding ascii .\outfile.txt -Value (
  (Get-Content -First 100 -ReadCount 100 .\file.txt) -join "`n") + "`n"
)
  • -First 100 дает указание Get-Content прочитать (максимум) 100 строк.

  • -ReadCount 100 вызывает чтение и вывод этих 100 строк сразу , в виде массива , который ускоряет чтение и последующую обработку.

    • Примечание: в PowerShell [Core] v7.0 + вы можете использовать сокращение -ReadCount 0 в сочетании с -First <n> означает: прочитать запрошенные строки <n> как один массив; из-за ошибки в более ранних версиях, включая Windows PowerShell, -ReadCount 0 всегда читает весь файл, даже при наличии -First (он же -TotalCount он же -Head).
      Кроме того, даже начиная с PowerShell [Core] 7.0.0-r c .2 (актуально на момент написания этой статьи), сочетание -ReadCount 0 с -Last <n> (иначе -Tail) должно быть избегать (на данный момент): в то время как полученный вывод правильный, за кадром снова весь файл , который читается; см. этот выпуск GitHub .
  • Обратите внимание на + "`n", который гарантирует, что выходной файл будет иметь завершающий символ новой строки как хорошо (какие текстовые файлы в мире Unix ожидаются).

Хотя вышеприведенное также работает с -Last <n> (-Tail <n>) для извлечения из конец файла, решение Тео (более медленное) Select-Object предлагает большую гибкость в отношении извлечения произвольных диапазонов строк благодаря доступным параметрам -Skip, -SkipLast и -Index ; однако, предлагая эти параметры также непосредственно на Get-Content для превосходной производительности, предлагается в этот запрос функции GitHub .

Также обратите внимание, что я использовал Set-Content вместо Out-File.
Если вы знаете, что пишете текст , Set-Content достаточно и обычно быстрее (хотя в этом случае это не имеет значения, учитывая, что записываемые данные передаются в виде одного значения .

Для полного обзора различий между Set-Content и Out-File / >, см. этот ответ .


Set-Content против Out-File тест:

Примечание : Этот тест сравнивает два командлета в отношении записи много входных строк , полученных через конвейер , в файл.

# Sample array of 100,000 lines.
$arr = (, 'foooooooooooooooooooooo') * 1e5
# Time writing the array lines to a file, first with Set-Content, then
# with Out-File.
$file = [IO.Path]::GetTempFileName()
{ $arr | Set-Content -Encoding Ascii $file }, 
{ $arr | Out-File -Encoding Ascii $file } | % { (Measure-Command $_).TotalSeconds }
Remove-Item $file

Пример времени в секундах от моего Windows 10 ВМ с Windows PowerShell v5.1:

2.6637108 # Set-Content
5.1850954 # Out-File; took almost twice as long.
1 голос
/ 10 февраля 2020

Вы можете объединить строки из командлета Get-Content с новой строкой Unix "` n "и сохранить их.

Что-то вроде

((Get-Content -Path .\wellmed_hce_elig_20191223.txt | 
        Select-Object -first 100) -join "`n") |
        Out-File -FilePath .\elig.txt -Encoding ascii -NoNewLine
...