在 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 的形式提供。
我正在尝试修复其中包含尾随 ,\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 的形式提供。