在 PowerShell 中替换 `,\r\n`

Replacing `,\r\n` in PowerShell

我正在尝试修复其中包含尾随 ,\r\n 的 CSV 文件。不管我做什么,它根本没有做任何事情。我尝试将表达式放在 [] 中,这使得它替换了每个逗号。这意味着问题在于它无法匹配换行符。

我使用 Sublime Text 保存了带有 Windows 行结尾的文件,并尝试了 \r\n\n\r\n 的两种变体。

(Get-Content file.txt) | ForEach-Object { $_ -replace '\,\r\n', [System.Environmen
t]::NewLine } | Set-Content file2.txt

我使用的是 PowerShell 版本 5.1.15063.413

PowerShell 原来相当...特别

Get-Content 默认 returns 一个字符串数组。它找到所有换行符并使用它们将输入拆分为所述数组。这意味着没有新行可供正则表达式匹配。

使用 -Raw 参数对该命令稍作修改,解决了我的问题。

(Get-Content file.txt -Raw).replace(",`r`n", [System.Environment]::NewLine) | Set-Content file2.txt

事实上,Get-Content 默认读取并发出输入文件的内容 逐行 ,带有任何风格的换行符 - CRLF、LF、 CR - 剥离.

虽然该行为可能不熟悉,但通常对处理管道中的文件有帮助

所示,-Raw 可用于完整读取文件 ,作为 取而代之的是单行多行字符串 - 这可以提供很好的性能优势.

举例说明方便逐行阅读 ],结合基于正则表达式的-replace operator对输入数组每个元素进行操作的能力(如果您的文件有LF (\n) 结尾,您正在选择性地寻找以 , 开头的流氓 CRLF (\r\n) 行结尾,但这无济于事,但是):

# Convenient, but can be made faster with -ReadCount 0 - see below.
@(Get-Content file.txt) -replace ',$' | Set-Content file2.txt

注:@(...)array-subexpression operator,用来保证Get-Content调用也输出一个数组 即使文件恰好只有 一个 行。

正则表达式锚 $ 匹配每个输入字符串(行)的末尾,实际上从每行中删除 尾随 ,存在的地方.


Get-Content性能说明:

如上文所述,-Raw 是迄今为止完整读取文本文件最快的方式 - 但设计 作为单个多行字符串.

默认行为,逐行读取很慢,尤其是因为 PowerShell 修饰每个输出行 与元数据[1](在-Raw的情况下,假设只有一个输出字符串,这只会发生 一次).

但是,您可以通过批量读取行 来加快速度 - 给定大小的行数组 - 使用 -ReadCount 参数,在这种情况下,只有每个数组而不是单独的行被修饰。 -ReadCount 0 所有 行读取到单个数组中。

注:

  • -ReadCount 更改流式传输行为 在管道中 :然后发送每个数组 作为一个整体通过管道,接收命令需要为计划,通常是通过对接收到的数组执行自己的枚举,例如使用foreach loop.

  • 相比之下,在 表达式 的上下文中使用 -ReadCount 0 会导致 没有行为差异,这意味着它可以用作简单的性能优化,不需要表达式的其他部分来适应它;以带有 -replace 运算的表达式为例:

    # Read all lines directly into an array, with -ReadCount 0,
    # instead of more slowly letting PowerShell stream the lines 
    # (emit them one by one) and then collect them in an array for you.
    # The -replace operator then acts on each element of the array.
    (Get-Content -ReadCount 0 file.txt) -replace ',$'
    

注意:@(...)在这种情况下不是,因为-ReadCount 0总是 发出一个数组,即使对于单行文件也是如此。

一种性能更好的逐行处理替代方案 - 虽然它不能直接用作表达式的一部分 -就是使用-switch statement with the -File parameter - see 来获取详细信息。


[1] 此元数据以 ETS (Extended Type System) properties, which notably provide information about the line number and the path of the originating file. Pipe a Get-Content call to | Format-List -Force to see these properties. While this extra information can be helpful, the performance impact of attaching it is noticeable. Given that the information is often not needed, having a least an opt-out would be helpful: see GitHub issue #7537 的形式提供。