如何保留 UNIX LF 行结尾?

How can I keep UNIX LF line endings?

我有一个大的 (9 GiB)、ASCII 编码、管道分隔的文件,带有 UNIX-style 行结尾; 0x0A.

我想将前 100 条记录抽样到一个文件中以供调查。以下将产生 100 条记录(1 header 条记录和 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 和 dos2unix。这些程序不在我的系统上,不允许安装。我搜索并找到了许多关于如何到达 CRLF 的地方。我还没有找到关于到达或保持 LF 的任何信息。

如何生成具有 LF 行尾而不是 CRLF 的文件?

您可以将 Get-Content cmdlet 中的行与 Unix“`n”换行符连接起来并保存。

类似

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

根据很少使用的 -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+ 中,您可以将 shorthand -ReadCount 0-First <n> 结合使用,表示:将请求的 <n> 行读取为单个数组;由于早期版本中的错误,包括 Windows PowerShell,-ReadCount 0 总是读取 整个 文件,即使存在 -First(又名 -TotalCount 又名 -Head).
      此外,即使从 PowerShell [Core] 7.0.0-rc.2(撰写本文时的当前版本)开始,将 -ReadCount 0-Last <n>(又名 -Tail) 应该避免(现在):虽然产生的输出是正确的,在幕后它又是整个文件被读取;参见 this GitHub issue
  • 注意 + "`n",它确保输出文件也有一个 trailing 换行符(Unix 世界中的文本文件是预计会有)。

虽然上面的方法也适用于 -Last <n> (-Tail <n>) 从文件的 end 中提取,Theo 的(较慢)Select-Object 解决方案在提取 任意范围 行方面提供了更大的灵活性,这要归功于可用参数 -Skip-SkipLast-Index;但是,在 this GitHub feature request.

中提议也 直接在 Get-Content 上提供这些参数以获得卓越的性能

另请注意,我使用了 Set-Content 而不是 Out-File
如果你知道你在写 textSet-Content 就足够了,而且通常 faster (尽管在这种情况下这无关紧要,因为要写入的数据作为 单个 值传递)。

要全面了解 Set-ContentOut-File / > 之间的 差异,请参阅 this answer


Set-Content 对比 Out-File 基准:

注意:此基准比较了两个 cmdlet 将通过管道 接收到的许多 输入字符串 写入文件。

# 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 PowerShell v5.1 的 Windows 10 VM 的示例计时(以秒为单位):

2.6637108 # Set-Content
5.1850954 # Out-File; took almost twice as long.