目次

PowerShellテキスト分割ツール

2024-08-31.3
オプション -ReadLine を -SplitLine に変更した

2024-08-31.2
アドバイスをもらってGet-Contentに-ErrorAction Stopを追加

2024-08-31
ちょっと作り直した

これは何?

指定のテキストファイルを指定の行数毎に分割するやっつけスクリプト。動作は少々重め。

使い方

PowerShellが実行可能な環境であるのは前提条件。
エラー処理を省いている。引数の範囲や指定漏れ等を確認していない。利用に際しては注意。

.\splitlog.ps1 -Path ログテキストファイル名
               -SkipLine 先頭からスキップする行数
               -LimitLine 読み込む最大行数
               -SplitLine 分割単位行数
               -Encode 文字コードエンコーディング

指定行数で分割する

以下はあるアプリケーションのログpdi.2024-01-20.logを1000行単位で分割する例。
この例だと、pdi.2024-01-20.log-001~008 の8ファイルに分割された。
表示されるタイプスタンプは処理開始日時。

d:\sandbox>powershell -File .\splitlog.ps1 -Path pdi.2024-01-20.log -SplitLine 1000
2024/08/31 18:54:35 Pos:0000000000, Start, Skip 0 Lines, Split 1000 Lines, All rows read.
2024/08/31 18:54:35 Pos:0000000001, Creating pdi.2024-01-20.log-001
2024/08/31 18:54:35 Pos:0000001001, Creating pdi.2024-01-20.log-002
2024/08/31 18:54:36 Pos:0000002001, Creating pdi.2024-01-20.log-003
2024/08/31 18:54:36 Pos:0000003001, Creating pdi.2024-01-20.log-004
2024/08/31 18:54:37 Pos:0000004001, Creating pdi.2024-01-20.log-005
2024/08/31 18:54:37 Pos:0000005001, Creating pdi.2024-01-20.log-006
2024/08/31 18:54:38 Pos:0000006001, Creating pdi.2024-01-20.log-007
2024/08/31 18:54:39 Pos:0000007001, Creating pdi.2024-01-20.log-008
2024/08/31 18:54:39 Pos:0000007320, Finished.

d:\sandbox>

指定行数を読み飛ばす

以下は先頭6500行をスキップして300行毎に分割している例。

d:\sandbox>powershell -File .\splitlog.ps1 -Path pdi.2024-01-20.log -SkipLine 6500 -SplitLine 300
2024/08/31 18:55:14 Pos:0000000000, Start, Skip 6500 Lines, Split 300 Lines, All rows read.
2024/08/31 18:55:14 Pos:0000006501, Creating pdi.2024-01-20.log-001
2024/08/31 18:55:14 Pos:0000006801, Creating pdi.2024-01-20.log-002
2024/08/31 18:55:14 Pos:0000007101, Creating pdi.2024-01-20.log-003
2024/08/31 18:55:14 Pos:0000007320, Finished.

d:\sandbox>

エンコーディングを指定する

以下はログの文字コード(エンコーディング)にUTF8を指定して2000行毎に分割する例。

d:\sandbox>powershell -File .\splitlog.ps1 -Path pdi.2024-01-20.log -SplitLine 2000 -Encode UTF8
2024/08/31 18:56:11 Pos:0000000000, Start, Skip 0 Lines, Split 2000 Lines, All rows read.
2024/08/31 18:56:11 Pos:0000000001, Creating pdi.2024-01-20.log-001
2024/08/31 18:56:12 Pos:0000002001, Creating pdi.2024-01-20.log-002
2024/08/31 18:56:13 Pos:0000004001, Creating pdi.2024-01-20.log-003
2024/08/31 18:56:14 Pos:0000006001, Creating pdi.2024-01-20.log-004
2024/08/31 18:56:15 Pos:0000007320, Finished.

d:\sandbox>

範囲を指定して分割する

以下は先頭5000行~6000行の間を500行毎に分割している例。

d:\sandbox>powershell -File .\splitlog.ps1 -Path pdi.2024-01-20.log -SkipLine 5000 -LimitLine 6000 -SplitLine 500
2024/08/31 18:58:05 Pos:0000000000, Start, Skip 5000 Lines, Split 500 Lines, Limit 6000 Line.
2024/08/31 18:58:06 Pos:0000005001, Creating pdi.2024-01-20.log-001
2024/08/31 18:58:06 Pos:0000005501, Creating pdi.2024-01-20.log-002
2024/08/31 18:58:06 Pos:0000006000, Finished.

d:\sandbox>

コード

とりあえずやっつけ。

splitlog.ps1
Param(
  $Path,
  $SplitLine=1000,
  $SkipLine=0,
  $LimitLine=0,
  $Encode="Default"
)
 
$SkipFlag = $true
$LineCounter = 0
$BreakCounter = 0
$FileNameIndex = 1
 
$SDate = Get-Date -DisplayHint DateTime
if ($LimitLine -eq 0) {
    Write-Host  ("{0} Pos:{1:0000000000}, Start, Skip {2} Lines, Split {3} Lines, All rows read." -f $SDate, 0, $SkipLine, $SplitLine)
}
else {
    Write-Host  ("{0} Pos:{1:0000000000}, Start, Skip {2} Lines, Split {3} Lines, Limit {4} Line." -f $SDate, 0, $SkipLine, $SplitLine, $LimitLine)
}
 
foreach($line in Get-Content -Path $Path -Encoding $Encode -ErrorAction Stop)
{
    $LineCounter++
 
    if ($SkipFlag -eq $true) {
        if (($SkipLine -eq 0) -or ($LineCounter -gt $SkipLine))
        {
            $SkipFlag = $false
        }
        else {
            continue
        }
    }
 
    if ($BreakCounter -eq 0) {
        $SplitPartFile = "{0}-{1:000}" -f $Path, $FileNameIndex
        $SDate         = Get-Date -DisplayHint DateTime
        $BeginLine     = $LineCounter
 
        Set-Content   -Path $SplitPartFile -Value ""
        Clear-Content -Path $SplitPartFile
 
        Write-Host  ("{0} Pos:{1:0000000000}, Creating {2}" -f $SDate, $BeginLine, $SplitPartFile)
    }
 
    $BreakCounter++
    Add-Content -Path $SplitPartFile -Value $line
 
    if ($BreakCounter -eq $SplitLine) {
        $FileNameIndex++
        $BreakCounter = 0
    }
 
    if (($LimitLine -ne 0) -and ($LineCounter -eq $LimitLine)) {
        break
    }
}
 
$SDate = Get-Date -DisplayHint DateTime
Write-Host  ("{0} Pos:{1:0000000000}, Finished." -f $SDate, $LineCounter)