web-dev-qa-db-ja.com

Powershellを使用してファイルから最後の行を削除します

使ってます

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

sSRSがCSVの下部に配置する空の行を削除します。

ただし、データが含まれている最後の行はCRLFで終わります(Notepad ++で表示)。これは削除されないため、技術的にはファイルの下部に空白行があります。

このCRLFを最後の行から削除する(そしてもちろんデータをそのまま維持する)方法はありますか?

13
stuartdotnet

ファイルの最後のものが削除したいCRLFであることをすでに知っている場合(そしてエンコーディングも知っている場合)、簡単なルートに進むことができます。

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

これは、ファイルのインプレース切り捨てです。すべてのファイルをメモリに読み込まなくても機能します(非常に大きなファイルがある場合は非常に便利です)。 ASCII、Latin- *、UTF-8で動作します。 UTF-16ではそのようには機能しません(その場合、最後から4バイトを削除する必要があります)。

最後の2バイトが本当に削除したいものであることを確認する追加のチェックを含めることができます。

$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のようなものではありませんが、700 MiBのデータベースダンプを処理する必要があったため、大きなファイルをメモリに完全に読み込むことには注意が必要です;)

14
Joey

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
7
Keith Hill

これが状況にどの程度当てはまるかはわかりませんが、テキストファイルの最後の行を削除するためのグーグル検索でここにたどり着き、上記の例/解決策は機能しませんでした。これは、これを機能させるために使用できたコマンドです。

$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

大きなファイルで作業している場合は、最初にこれを一時ファイルにパイプすることをお勧めします。

2
Geoff Dawdy

「UCS-2リトルエンディアン」ファイル形式の場合は、次を使用します。

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

これを試してください。ただし、ファイルからすべての空の行が削除されます。

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