LoginSignup
8
9

More than 5 years have passed since last update.

F#でPowerShellのカスタムコマンドレットを作ってみた

Posted at

まずは参照設定。
System.Management.Automation.dll はGACから。
System.Configuration.Install はVisual Studio の参照マネージャのフレームワークにあるもの。

そしてこんなコードを書いてみた。

open System
open System.ComponentModel
open System.IO
open System.Management.Automation

type SpecifiedLinesData(data) =
    member val Data = Some(data) with get 

[<Cmdlet(VerbsCommon.Select, "SpecifiedLines", SupportsShouldProcess=true)>]
type SelectSpecifiedLinesCommand() =
    inherit PSCmdlet()

    let inputLines data file =
        match data with
        | Some(x) -> x
        | None ->
            use r = 
                if String.IsNullOrEmpty(file)
                then Console.In
                else new StreamReader(file) :> TextReader
            seq {
                while r.Peek()>= 0 do
                    yield r.ReadLine()
            }
            |> Seq.toList :> seq<string>

    let outputLines data file =
        use w = 
            if String.IsNullOrEmpty(file)
            then Console.Out
            else new StreamWriter(file) :> TextWriter

        for s : string in data do
            w.WriteLine(s)

    [<Parameter>]
    member val InFile = "" with get, set
    [<Parameter>]
    member val OutFile = "" with get, set
    [<Parameter(DontShow=true, ValueFromPipelineByPropertyName=true)>]
    member val Data = None with get, set
    [<Parameter(Mandatory=true)>]
    member val MaxLineLength = 0 with get, set

    override this.ProcessRecord() =
        let d =
            inputLines this.Data this.InFile
            |> Seq.filter (fun x -> x.Length <= this.MaxLineLength)

        outputLines d this.OutFile

        base.WriteObject(new SpecifiedLinesData(d))

[<RunInstaller(true)>]
type SelectSpecifiedLinesCmdlets() =
    inherit PSSnapIn()
    override val Name = "SelectSpecifiedLinesCmdlets" with get
    override val Vendor = "minfuk" with get
    override val Description = "Select SpecifiedLines Cmdlets" with get

クラスライブラリとしてビルドしてできた.dllをPowerShellに登録。
F#だからと言って特別に必要な手順もなく、普通に登録する手順(installutil の後にPowerShell上でAdd-PSSnapIn)でOKでした。

で次のような sample.txt を作って、

sample.txt
7aaaaaa
8bbbbbbb
2c
4ddd
9eeeeeeee
5ffff
3gg
6hhhhh
1

こんな感じで実行。

Select-SpecifiedLines -InFile {sample.txtのフルパス} -MaxLineLength 7

すると結果は、

7aaaaaa
2c
4ddd
5ffff
3gg
6hhhhh
1

Data
----
Some(Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers+mkSeq@550[System.String])

-MaxLineLength に指定した7文字以下の長さの行だけ抽出できた。

さらに次のようにパイプラインでつなげてみると、

Select-SpecifiedLines -InFile {sample.txtのフルパス} -MaxLineLength 7 | Select-SpecifiedLines -MaxLineLength 4

結果は、

7aaaaaa
2c
4ddd
5ffff
3gg
6hhhhh
1
2c
4ddd
3gg
1

Data
----
Some(Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers+mkSeq@550[System.String])

-MaxLineLength に指定した7文字以下の長さの行だけ抽出した後で、その次に-MaxLineLength に指定した4文字以下の長さの行だけ抽出できた。

8
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
9