LoginSignup
18
20

More than 5 years have passed since last update.

コマンドラインツールの作り方

Posted at

サーバの管理などでBashなどを使ってバッチ処理のスクリプトを書くことが時々あるのですが、今回はそれをElixirで行ってみようと思います。
Elixirにはelixirコマンドがあり、これを使用することでElixirのスプリクトを実行することができます。

ファイルの拡張子はElixirスクリプトの命名規則に倣って.exsとします。
最初の行にはシェバンを記述します。
標準ライブラリだけを使うのであればmix newをする必要はなく、適当な場所にファイルを作ればOKです。

hello.exs
#!/usr/bin/env elixir
IO.puts "Hello world!"

ファイルを保存したら、chmodコマンドで実行権限を与えて実行してみます。

$ chmod +x hello.exs
$ ./hello.exs
Hello world!

簡単ですね。
次はコマンドライン引数を受け取って1つづつ表示をしてみます。

argv.exs
#!/usr/bin/env elixir
System.argv()
|> Enum.each(fn(x) -> IO.puts x end)
$ chmod +x argv.exs
$ ./argv.exs foo bar
foo
bar

System.argv()はリストを返すのでEnumにある関数でデータをいろいろ加工することができます。
引数で渡された数値を足すスクリプトを作ってみます。
コマンドライン引数は文字列型なので、いったん数値型に変換してから足しあわせます。

calc.exs
#!/usr/bin/env elixir
System.argv()
|> Enum.map(fn(x) -> String.to_integer x end)
|> Enum.sum
|> IO.puts
$ chmod +x calc.exs
$ ./calc.exs 1 2 3 4
10

次はパイプでlsコマンドから出力されたディレクトリのリストをElixirスクリプトで受け取ります。
受け取った際に正規表現を使って拡張子に.exsを持つファイルだけに絞り込むようにします。

pipe.exs
#!/usr/bin/env elixir
IO.stream(:stdio, :line)
|> Enum.filter(fn(x) -> x =~ ~r/\.exs/ end)
|> Enum.each(fn(x) -> IO.write(:stdio, x) end)
$ chmod +x pipe.exs
$ ls -la | ./pipe.exs
-rwxr-xr-x    1 hideshi  staff    73 12  1 06:58 args.exs
-rwxr-xr-x    1 hideshi  staff   105 12  1 07:01 calc.exs
-rwxr-xr-x    1 hideshi  staff    44 12  1 06:33 hello.exs
-rwxr-xr-x    1 hideshi  staff   138 12  1 07:11 pipe.exs

ElixirスクリプトからOSコマンドを実行することもできます。
この記事が詳しいです。

cmd.exs
#!/usr/bin/env elixir
{result, 0} = System.cmd "ls", ["-la"]
result
|> String.split("\n")
|> Enum.filter(fn(x) -> x =~ ~r/\.exs/ end)
|> Enum.each(fn(x) -> IO.puts x end)
$ chmod +x cmd.exs
$ ./cmd.exs
-rwxr-xr-x    1 hideshi  staff    73 12  1 06:58 args.exs
-rwxr-xr-x    1 hideshi  staff   105 12  1 07:01 calc.exs
-rwxr-xr-x    1 hideshi  staff   171 12  1 07:54 cmd.exs
-rwxr-xr-x    1 hideshi  staff    44 12  1 06:33 hello.exs
-rwxr-xr-x    1 hideshi  staff   138 12  1 07:11 pipe.exs

標準出力に出力していますので、その後でパイプで他のコマンドに渡すこともできます。
grepで文字列calcを含む行だけ抽出してみます。

$ ./cmd.exs |grep calc
-rwxr-xr-x    1 hideshi  staff   105 12  1 07:01 calc.exs

最後にコマンドラインオプションをパースしてみましょう。

opt.exs
#!/usr/bin/env elixir
System.argv
|> OptionParser.parse
|> IO.inspect
$ chmod +x opt.exs
$ ./opt.exs -x --debug --verbose -c foo bar
{[debug: true, verbose: true], ["bar"], [{"-x", nil}, {"-c", "foo"}]}

うまくパースできたようですね。

もし他にも便利な機能があればコメント頂ければと思います。

18
20
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
18
20