简体   繁体   English

使用Powershell从文件中删除最后一行

[英]Remove last line from file with Powershell

I am using 我在用

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

to remove the empty lines that SSRS puts at the bottom of my CSVs. 删除SSRS放在CSV底部的空行。

However, the last line, which has data on it, ends with a CRLF (as viewed in Notepad++) - and this is not removed, so technically there is still a blank line at the bottom of the file. 但是,最后一行(包含数据)以CRLF结尾(如Notepad ++中所示) - 并未删除,因此从技术上讲,文件底部仍有一个空行。

Is there a way to remove this CRLF from the last line (and keep the data intact, of course)? 有没有办法从最后一行删除这个CRLF(并保持数据完好无损)?

If you already know that the very last thing of the file is a CRLF you want to get rid of (and you know the encoding too) you can go the quick route: 如果你已经知道文件的最后一件事是CRLF你想要摆脱(你也知道编码)你可以走快速路线:

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

This is an in-place truncation of the file. 这是文件的就地截断。 It works without reading all the file into memory (very nice if you have a very large file). 它可以在不将所有文件读入内存的情况下工作(非常好,如果你有一个非常大的文件)。 It works for ASCII, Latin-* and UTF-8. 它适用于ASCII,Latin- *和UTF-8。 It won't work that way for UTF-16 (you'd have to remove four bytes from the end, in that case). 对于UTF-16,它将无法正常工作(在这种情况下,您必须从末尾删除四个字节)。

You can include an additional check that the last two bytes are really what you want to remove: 您可以包含一个额外的检查,表明最后两个字节确实是您要删除的内容:

$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()

Again, adapt if you use another encoding, eg for UTF-16 you need to compare to either 0,10,0,13 or 10,0,13,0 . 再次,如果您使用其他编码,请进行调整,例如对于UTF-16,您需要与0,10,0,1310,0,13,0进行比较。

Agreed, this is not very PowerShell-ey, but ever since I had to process a 700-MiB database dump I am wary of reading potentially large files into memory completely ;) 同意,这不是PowerShell-ey,但自从我不得不处理700-MiB数据库转储以来,我一直担心将可能存在的大文件完全读入内存;)

When you read a file using Get-Content it streams each line down the pipe as a string. 当您使用Get-Content读取文件时,它会将每一行作为字符串流入管道。 When Out-File (essentially what > is an alias for) gets these strings, it always appends a line terminator sequence. Out-File (基本上是什么>是别名)获取这些字符串时,它总是附加行终止符序列。 Try the following if the files are not too big: 如果文件不是太大,请尝试以下操作:

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

This is the file before: 这是之前的文件:

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..

and after: 之后:

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

I'm not sure how applicable this is to the situation but my google search for removing the last line of a text file led me here and the above examples/solutions didn't work. 我不确定这种情况有多适用,但我谷歌搜索删除文本文件的最后一行导致我在这里,上面的例子/解决方案不起作用。 This is the command I was able to use to get this to work: 这是我能够用来使其工作的命令:

$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

If you are working with a large file you may want to pipe this to a temp file first. 如果您正在使用大文件,则可能需要先将其传输到临时文件。

For 'UCS-2 Little Endian' file format, use this: 对于'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()

Try this, though it will remove ALL empty lines from your file 试试这个,虽然它会从你的文件中删除所有空行

(Get-Content c:\FileWithEmptyLinesAtEnd.txt) | 
Where-Object {$_ -match '\S'} | 
Out-File c:\FileWithEmptyLinesAtEnd.txt

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM