注意:以下解决方案按行号从任何基于文本的文件中删除单行.正如marsze指出的那样,其他注意事项可能适用于CSV文件,其中必须注意不要消除标题行,如果行具有嵌入换行符的值,则行可以跨越多行; 在这种情况下,使用CSV解析器是更好的选择.
如果性能不是最重要的,这里有一个基于管道的内存管理方式:
Get-Content file.txt |
Where-Object ReadCount -ne 1005 |
Set-Content -Encoding Utf8 new-file.txt
Run Code Online (Sandbox Code Playgroud)
Get-Content为.ReadCount它输出的每一行添加一个(有点模糊命名的)属性,其中包含1基于行的行号.
请注意,输入文件的字符编码不会被保留Get-Content,因此您应该Set-Content使用UTF-8作为示例显式控制'st输出编码,如上所示.
如果不将整个文件作为一个整体读入内存,则必须至少暂时输出到新文件; 您可以使用临时输出文件替换原始文件
Move-Item -Force new-file.txt file.txt
基于直接使用.NET框架的更快但内存密集的替代方案,它还允许您更新文件:
$file = 'file.txt'
$lines = [IO.File]::ReadAllLines("$PWD/$file")
Set-Content -Encoding UTF8 $file -Value $lines[0..1003 + 1005..($lines.Count-1)]
Run Code Online (Sandbox Code Playgroud)
注意需要使用"$PWD/$file",即显式地将当前目录路径前置到存储在其中的相对路径$file,因为.NET框架对当前目录的概念与PowerShell的不同.
$lines = Get-Content $file在功能上等同于$lines = [IO.File]::ReadAllLines("$PWD/$file")它,但它的表现会明显变差.0..1003创建从索引数组0来1003; 通过输入数组的其余部分+将该数组与索引连接起来1005; 请注意,数组索引是0基于的,而行号是1基于的.
还注意到得到的阵列是如何传递到Set-Content作为直接参数通过-Value,这是比经由管线(通过它更快... | Set-Content ...),其中,将执行元件逐元素的处理.
最后,一个比基于管道的方法更快的内存友好方法:
$file = 'file.txt'
$outFile = [IO.File]::CreateText("$PWD/new-file.txt")
$lineNo = 0
try {
foreach ($line in [IO.File]::ReadLines("$PWD/$file")) {
if (++$lineNo -eq 1005) { continue }
$outFile.WriteLine($line)
}
} finally {
$outFile.Dispose()
}
Run Code Online (Sandbox Code Playgroud)
与基于管道的命令一样,您可能必须在之后用新文件替换原始文件.
| 归档时间: |
|
| 查看次数: |
405 次 |
| 最近记录: |