15

我在用

gc FileWithEmptyLines.txt | where {$_ -ne ""} > FileWithNoEmptyLines.txt

删除 SSRS 放在我的 CSV 底部的空行。

但是,包含数据的最后一行以 CRLF 结尾(如在 Notepad++ 中查看的那样) - 这并没有被删除,因此从技术上讲,文件底部仍然有一个空白行。

有没有办法从最后一行删除这个 CRLF(当然,保持数据完整)?

4

5 回答 5

18

如果您已经知道文件的最后一件事是您想要摆脱的 CRLF(并且您也知道编码),您可以走捷径:

$stream = [IO.File]::OpenWrite('foo.txt')
$stream.SetLength($stream.Length - 2)
$stream.Close()
$stream.Dispose()

这是文件的就地截断。它无需将所有文件读入内存即可工作(如果您有一个非常大的文件,那就太好了)。它适用于 ASCII、Latin-* 和 UTF-8。它不适用于 UTF-16(在这种情况下,您必须从末尾删除四个字节)。

您可以额外检查最后两个字节是否真的是您要删除的内容:

$stream = [IO.File]::Open('foo.txt', [IO.FileMode]::Open)
$stream.Position = $stream.Length - 2
$bytes = 0..1 | %{ $stream.ReadByte() }
$compareBytes = 13,10 # CR,LF
if ("$bytes" -eq "$compareBytes") {
    $stream.SetLength($stream.Length - 2)
}
$stream.Close()
$stream.Dispose()

同样,如果您使用其他编码进行调整,例如对于 UTF-16,您需要与0,10,0,13或进行比较10,0,13,0

同意,这不是很 PowerShell-ey,但是自从我不得不处理 700-MiB 的数据库转储后,我对将潜在的大文件完全读入内存持谨慎态度;)

于 2012-07-25T07:33:41.913 回答
7

当您使用它读取文件Get-Content时,将管道中的每一行作为字符串流式传输。当Out-File(本质上>是别名)获取这些字符串时,它总是附加一个行终止符序列。如果文件不是太大,请尝试以下操作:

$text = [IO.File]::ReadAllText("c:\FileWithEmptyLinesAtEnd.txt")
[IO.File]::WriteAllText("c:\FileWithEmptyLinesAtEnd.txt", $text.TrimEnd())

这是之前的文件:

14> fhex .\FileWithEmptyLinesAtEnd.txt

Address:  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F ASCII
-------- ----------------------------------------------- ----------------
00000000 73 65 72 76 65 72 31 2C 73 65 72 76 65 72 32 2E server1,server2.
00000010 64 6F 6D 61 69 6E 2E 6C 6F 63 61 6C 2C 73 65 72 domain.local,ser
00000020 76 65 72 33 0D 0A 20 20 20 20 20 20             ver3..

之后:

19> fhex .\FileWithEmptyLinesAtEnd.txt

Address:  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F ASCII
-------- ----------------------------------------------- ----------------
00000000 73 65 72 76 65 72 31 2C 73 65 72 76 65 72 32 2E server1,server2.
00000010 64 6F 6D 61 69 6E 2E 6C 6F 63 61 6C 2C 73 65 72 domain.local,ser
00000020 76 65 72 33                                     ver3
于 2012-07-25T05:27:48.163 回答
2

我不确定这对这种情况有多适用,但我的谷歌搜索删除了文本文件的最后一行导致我来到这里,上面的示例/解决方案不起作用。这是我可以用来让它工作的命令:

$file = "file.txt"
Get-Content $file | Measure-Object -Line
$a = (Get-Content $file | Measure-Object)
(Get-Content $file) | ? {($a.count-1)-notcontains $_.ReadCount} | Set-Content $file

如果您正在处理一个大文件,您可能希望首先将其通过管道传输到一个临时文件。

于 2013-01-10T19:43:43.110 回答
1

对于“UCS-2 Little Endian”文件格式,请使用:

$stream = [IO.File]::Open($filename, [IO.FileMode]::Open)
$stream.Position = $stream.Length - 4
$bytes = 0..3 | %{ $stream.ReadByte() }
$compareBytes = 13,0,10,0 # CR,LF
echo "bytes: "$bytes
if ("$bytes" -eq "$compareBytes")
{
    $stream.SetLength($stream.Length - 4)
}
$stream.Close()
$stream.Dispose()
于 2012-11-15T18:57:15.320 回答
0

试试这个,虽然它会从你的文件中删除所有空行

(Get-Content c:\FileWithEmptyLinesAtEnd.txt) | 
Where-Object {$_ -match '\S'} | 
Out-File c:\FileWithEmptyLinesAtEnd.txt
于 2012-07-25T07:27:43.217 回答