tech.guitarrapc.cóm

C#, PowerShell, Unity, Cloud, Serverless Technical Update and Features

Powershellで文字長を揃えてみたりする

小ネタです。 面白くもなんともないのですが、まぁ固定長の時とかに使えば同でしょうか (( 業務システムで取り込む際などに、csvの固定長でとか言われる事があるような無いような。 今時csvとか思いますが、現実は現実です。 実際経験上多いのです。 そこで、Perlで良くやるような固定長でのデータ出力をPowerShellでやる一例です。

文字長を揃える

とりあえずコードを見れば分かるかと。
$testText1 = 'abcdefghijklmnopqrstuvwxyz' #26文字です
$testText2 = '123456789012345678901234567890' #30文字です

$textLength = 15
$testText1 = $testText1.PadRight($textLength).SubString(0, $textLength)
$testText2 = $testText2.PadRight($textLength).SubString(0, $textLength)
で取り出してみると
$testText1 + "<-ここまで"
$testText2 + "<-ここまで"
結果は15文字で(ぶった切って……整えられています!
abcdefghijklmno<-ここまで
123456789012345<-ここまで

簡単な説明

説明も何もと言われそうですが簡単に。 .PadRight()メソッドで文字列を左寄せ + 指定した文字数に達しない場合は空白を右側に埋め込んでいます。
MSDN - String.PadRight メソッド
次に、.Substring()メソッドで文字を切り取る必要があります。 PadRight()メソッドで出力しても文字が減るのではないかって?いいえ、減りません。
MSDN - String.Substring メソッド
PowerShellのようなスクリプト言語では、この辺の文字列操作は頻繁に使うのですね。

文字をスペースで埋めてFunction化

簡単に使うならやはりFucntion化してあると便利なものです。 ということで、お手軽Functionをどうぞ。 これでCSV出力前に、特定カラムだけ固定長文字列に組み込むのも簡単ですね。 単にスペース埋めでのファンクションです。 スイッチで、右埋め、左埋めを選べます。(デフォルト右埋め)
function Get-SpecificLengthString{

    [CmdletBinding(  
        SupportsShouldProcess = $false,
        ConfirmImpact = "none",
        DefaultParameterSetName = "PadRight"
    )]

    param
    (
        [Parameter(
        HelpMessage = "Input length int you want to output",
        Position = 0,
        Mandatory = $true,
        ValueFromPipeline = $true,
        ValueFromPipelineByPropertyName = $true
        )]
        [ValidateNotNullOrEmpty()]
        [int]
        $textlength,

        [Parameter(
        HelpMessage = "Input String you want to output as specific length",
        Position = 1,
        Mandatory = $true,
        ValueFromPipeline = $true,
        ValueFromPipelineByPropertyName = $true
        )]
        [ValidateNotNullOrEmpty()]
        [string]
        $textInput,

        [Parameter(
        HelpMessage = "Select if you want to output as PadRight",
        Mandatory = $false,
        ValueFromPipeline = $true,
        ValueFromPipelineByPropertyName = $true,
        ParameterSetName="PadRight"
        )] 
        [switch]
        $PadRight,

        [Parameter(
        HelpMessage = "Select if you want to output as PadLeft",
        Mandatory = $false,
        ValueFromPipeline = $true,
        ValueFromPipelineByPropertyName = $true,
        ParameterSetName="PadLeft"
        )] 
        [switch]
        $PadLeft

    )

    begin
    {

    }

    process
    {
        switch ($true) {
        $PadRight {$textOutput = $textInput.PadRight($textLength).SubString(0, $textLength)}
        $PadLeft {$textOutput = $textInput.PadLeft($textLength).SubString(0, $textLength)}
        }
    }

    end
    {
        return $textOutput

    }
}
利用時はこう。
[string]$testText = 'abcdefghijklmnopqrstuvwxyz'
$testText += '123456789012345678901234567890'
$testText += '098765'
$testText += 'asdfghjk'

$testText | %{Get-SpecificLengthString -textlength 15 -textInput $_ -PadRight}
$testText | %{Get-SpecificLengthString -textlength 15 -textInput $_ -PadLeft}
左寄せ出力例です。
abcdefghijklmno
123456789012345
098765         
asdfghjk       
右寄せ出力例です。
abcdefghijklmno
123456789012345
         098765
       asdfghjk

文字をスペースで埋めてFunction化

なんだか埋める文字も選べる方がいいとか言われそうだったので、一応用意しました。 同様に、スイッチで、右埋め、左埋めを選べます。(デフォルト右埋め) こちらは、デフォルトスペース埋めです。 (パラメーター指定しないとスペース埋め)
function Get-SpecificLengthStringPadWith{

    [CmdletBinding(  
        SupportsShouldProcess = $false,
        ConfirmImpact = "none",
        DefaultParameterSetName = "PadRight"
    )]

    param
    (
        [Parameter(
        HelpMessage = "Input length int you want to output",
        Position = 0,
        Mandatory = $true,
        ValueFromPipeline = $true,
        ValueFromPipelineByPropertyName = $true
        )]
        [ValidateNotNullOrEmpty()]
        [int]
        $textlength,

        [Parameter(
        HelpMessage = "Input String you want to output as specific length",
        Position = 1,
        Mandatory = $true,
        ValueFromPipeline = $true,
        ValueFromPipelineByPropertyName = $true
        )]
        [ValidateNotNullOrEmpty()]
        [string]
        $textInput,

        [Parameter(
        HelpMessage = "Input String you want to Pad with. default is space: ' '",
        Mandatory = $false,
        ValueFromPipeline = $true,
        ValueFromPipelineByPropertyName = $true
        )]
        [string]
        $padString=" ",

        [Parameter(
        HelpMessage = "Select if you want to output as PadRight",
        Mandatory = $false,
        ValueFromPipeline = $true,
        ValueFromPipelineByPropertyName = $true,
        ParameterSetName="PadRight"
        )] 
        [switch]
        $PadRight,

        [Parameter(
        HelpMessage = "Select if you want to output as PadLeft",
        Mandatory = $false,
        ValueFromPipeline = $true,
        ValueFromPipelineByPropertyName = $true,
        ParameterSetName="PadLeft"
        )] 
        [switch]
        $PadLeft

    )

    begin
    {

    }

    process
    {
        switch ($true) {
        $PadRight {$textOutput = $textInput.PadRight($textLength,$padString).SubString(0, $textLength)}
        $PadLeft {$textOutput = $textInput.PadLeft($textLength,$padString).SubString(0, $textLength)}
        }
    }

    end
    {
        return $textOutput

    }
}
利用時はこう。
[string]$testText = 'abcdefghijklmnopqrstuvwxyz'
$testText += '123456789012345678901234567890'
$testText += '098765'
$testText += 'asdfghjk'

$testText | %{Get-SpecificLengthStringPadWith -textlength 15 -textInput $_ -PadRight -padString "0"}
$testText | %{Get-SpecificLengthStringPadWith -textlength 15 -textInput $_ -PadLeft -padString "a"}
$testText | %{Get-SpecificLengthStringPadWith -textlength 15 -textInput $_ -PadLeft} #空白埋めは-padString省略可能
左寄せ、0埋めの出力例です。
abcdefghijklmno
123456789012345
098765000000000
asdfghjk0000000
右寄せ、a埋めの出力例です。
abcdefghijklmno
123456789012345
aaaaaaaaa098765
aaaaaaaasdfghjk
右寄せ、スペース埋めの出力例です。
abcdefghijklmno
123456789012345
         098765
       asdfghjk