<# .SYNOPSIS ソート & ユニーク .PARAMETER mode 動作モード 0:ソート 1:ソート & ユニーク 2:ソート & ユニーク(重複数を出力) 3:ソート & ユニーク(重複していない行を出力。重複数も出力) 4:ソート & ユニーク(重複している行を出力。重複数も出力) .PARAMETER index ソート & ユニークする位置を指定する。 0:1 文字目から n 文字。(左端) 1:m 文字目以降。 (右端) 2:m 文字目から n 文字。(中央) .PARAMETER SJIS ソート & ユニークをキャラクタコード「シフト JIS」で行う。 省略時はユニコードで行う。 .EXAMPLE Get-Context .\input.txt | uq .EXAMPLE Get-Context .\input.txt | uq -index 0,3 .EXAMPLE Get-Context .\input.txt | uq -index 1,3 .EXAMPLE Get-Context .\input.txt | uq -index 2,4,5 .INPUTS 標準入力。 .OUTPUTS 標準出力。 #>
Param ( [Int32] $mode = 1, [Int32[]] $index, [Switch] $SJIS ) $context = @{} if( $SJIS ) { $context.enc = [System.Text.Encoding]::Default } else { $context.enc = [System.Text.Encoding]::Unicode } # 0 … 1 文字目から n 文字。(左端) # 1 … m 文字目以降。 (右端) # 2 … m 文字目から n 文字。(中央) if( $index -ne $Null ) { switch( $index[0] ) { 0 { if( $index.Count -lt 2 ) { Write-Host '引数不足' return 1 } $context.nStart = 0 $context.nLength = $index[1] } 1 { if( $index.Count -lt 2 ) { Write-Host '引数不足' return 1 } $context.nStart = $index[1] $context.nLength = [Int32]::MaxValue } 2 { if( $index.Count -lt 3 ) { Write-Host '引数不足' return 1 } $context.nStart = $index[1] $context.nLength = $index[2] } default { Write-Host '引数 -index 異常' return 1 } } } else { $context.nStart = 0 $context.nLength = [Int32]::MaxValue } Function Extract-Line-Part( [String] $line, $context ) { [Int32] $nStart = $context.nStart [Int32] $nLength = $context.nLength if( $nStart -gt $line.Length ) { $nStart = 0 $nLength = 0 } else { if( ($nStart + $nLength) -gt $line.Length ) { $nLength = $line.Length - $nStart } } $line.Substring($nStart, $nLength) } Function In-Binary-List( [System.Collections.Generic.List[Object]] $ls ) { Process { $linePart = Extract-Line-Part $line $context $i = @{} $i.stream = $context.enc.GetBytes( $linePart ) $i.line = $line $i.count = 0 $ls.Add( $i ) } } Function In-Text-List( [System.Collections.Generic.List[Object]] $ls ) { Process { $linePart = Extract-Line-Part $line $context $i = @{} $i.stream = $linePart $i.line = $line $i.count = 0 $ls.Add( $i ) } } Function Display-Factor { Process { $_.line } } Function Display-FactorAll { Process { $_.line + "`t-->" + "`t" + $_.count } } Function Uniq-Filter { Process { if( $_.count -ge 1 ) { $_ } } } Function Single-Filter { Process { if( $_.count -eq 1 ) { $_ } } } Function Duplicate-Filter { Process { if( $_.count -ge 2 ) { $_ } } } Function Compare-Binary( [Byte[]] $l, [Byte[]] $r ) { [Int32] $diff = $l.Count - $r.Count if( $diff -eq 0 ) { if( $l.Count -eq 0 ) { return 0 } $min = $l.Count } else { if( $l.Count -eq 0 ) { return -1 } if( $r.Count -eq 0 ) { return 1 } if( $diff -lt 0 ) { $min = $l.Count } else { $min = $r.Count } } for( $i = 0; $i -lt $min; $i ++ ) { [Int32] $nValueL = $l[$i] [Int32] $nValueR = $r[$i] $n = $nValueL - $nValueR if( $n -ne 0 ) { if( $n -lt 0 ) { return -1 } else { return 1 } } } if( $diff -ne 0 ) { if( $diff -lt 0 ) { return -1 } else { return 1 } } return 0 } Function Sort-Binary-List( [System.Collections.Generic.List[Object]] $ls ) { for( $y = 0; $y -lt $ls.Count - 1; $y ++ ) { $itemY = $ls[$y] for( $x = $y + 1; $x -lt $ls.Count; $x ++ ) { $itemX = $ls[$x] $r = Compare-Binary $itemY.stream $itemX.stream if( $r -gt 0 ) { $ls[$y] = $itemX $ls[$x] = $itemY $itemY = $itemX } } } } Function Sort-Text-List( [System.Collections.Generic.List[Object]] $ls ) { for( $y = 0; $y -lt $ls.Count - 1; $y ++ ) { $itemY = $ls[$y] for( $x = $y + 1; $x -lt $ls.Count; $x ++ ) { $itemX = $ls[$x] $r = [System.String]::Compare( $itemY.stream, $itemX.stream ) if( $r -gt 0 ) { $ls[$y] = $itemX $ls[$x] = $itemY $itemY = $itemX } } } } Function Binary-Uniq-Count { Begin { $base = $Null } Process { $line = $_ if( $base -eq $Null ) { $base = $line $base.count = 1 } else { $r = Compare-Binary $base.stream $line.stream if( $r -ne 0 ) { $base = $line $base.count = 1 } else { $base.count ++; } } } } Function Text-Uniq-Count { Begin { $base = $Null } Process { $line = $_ if( $base -eq $Null ) { $base = $line $base.count = 1 } else { if( $base.stream.Equals($line.stream) -eq 0 ) { $base = $line $base.count = 1 } else { $base.count ++; } } } } $list = [System.Collections.Generic.List[Object]]::new() if( $SJIS ) { ($($Input)) | In-Binary-List $list Sort-Binary-List $list } else { ($($Input)) | In-Text-List $list Sort-Text-List $list } switch( $mode ) { 0 { # 0 … ソート $list | Display-Factor } {$_ -in 1,2,3} { # 1 … ユニーク # 2 … ソート & ユニーク(重複数を出力) # 3 … ソート & ユニーク(重複していないものを出力) # 4 … ソート & ユニーク(重複しているものを出力) if( $SJIS ) { $list | Binary-Uniq-Count } else { $list | Text-Uniq-Count } } 1 { # 1 … ユニーク $list | Uniq-Filter | Display-Factor } 2 { # 2 … ソート & ユニーク(重複数を出力) $list | Uniq-Filter | Display-FactorAll } 3 { # 3 … ソート & ユニーク(重複していないものを出力) $list | Single-Filter | Display-FactorAll } 4 { # 4 … ソート & ユニーク(重複しているものを出力) $list | Duplicate-Filter | Display-FactorAll } }