tech.guitarrapc.cóm

Technical updates

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 メソッド.aspx)

次に、.Substring()メソッドで文字を切り取る必要があります。 PadRight()メソッドで出力しても文字が減るのではないかって? いいえ、減りません。

MSDN - String.Substring メソッド.aspx)

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