Perl Hackers Hub

第45回 Perlで作るコマンドラインツール―オプション,サブコマンド,設定ファイルへの対応(2)

この記事を読むのに必要な時間:およそ 3 分

コマンドラインツールの入出力

ここまで,コマンドラインツールでよく使われるコマンドライン引数と設定ファイルについて説明しました。それ以外に重要なのは,データの入出力です。本節ではコマンドラインツールのデータ入出力にあたってのTipsや,利用すると便利なモジュールを紹介していきます。

IO::Prompt::Simpleを使ったインタラクティブな入力

コマンドラインツールを実行する際,途中でユーザーからの入力を受け付けたい場合があります。たとえば復旧の難しい処理(ファイル削除など)を行う前に,本当に実行してよいかユーザーに確認するなどです。IO::Prompt::Simpleを使うと,こういったケースに対応するコードをシンプルに記述できます。

use IO::Prompt::Simple;

# 前処理

my $answer =
    prompt 'ファイルの削除を実施します。よろしいですか? (y/N)',
    'N';

if ($answer eq 'y') {
    # ファイル削除
} elsif ($answer eq 'N') {
    print "ファイルの削除をキャンセルしました\n";
    exit;
} else {
    die 'invalid input';
}

prompt関数の第1引数にはユーザーへのメッセージ,第2引数にはデフォルト値を指定します。ユーザーが何も入力せずに[Enter]を押した場合は,デフォルト値がpromptの戻り値として返ってきます。

prompt関数の第2引数がスカラ値の場合はデフォルト値として扱われますが,ハッシュリファレンスを渡して細かな設定を行うこともできます。たとえば先ほどのコードのように確認メッセージにyes/noで答えてもらうようなケースでは,入力するデータを制限して次のように書くことができます。

use IO::Prompt::Simple;

my $answer =
     prompt 'ファイル削除を実施します。よろしいですか?',
            { anyone => [qw/y N/], ignore_case => 1 };

詳しくは,IO::Prompt::Simpleのドキュメントを参照してください。

環境変数からの入力

本項では環境変数から入力を受け付ける方法を説明します。ここまで紹介したコマンドライン引数を使う方法,ファイルから設定を読み込む方法,標準入力からデータを読み込む方法を使い分けることで,ほとんどのユースケースに対応できます。そのうえであえて環境変数を使うメリットはなんでしょうか。一例としては,TERM変数やLANG変数など,OS環境の情報が入っている環境変数を取得できることが挙げられます。また,crontabで複数のコマンドの実行計画を定義している場合,冒頭で環境変数の設定を定義しておけば,すべてのコマンドでその設定を参照できます。

MAILTO=report@example.com

0 * * * * /path/to/cmd1.pl
30 1 * * * /path/to/cmd2.pl

上記のように記述すれば,cmd1.plでもcmd2.plでも$ENV{MAILTO} でレポート送信先メールアドレスreport@example.comを参照できます。

ほかに,HerokuやGoogle App EngineなどのPaaSPlatform as a Service環境では,実行するプログラムへ設定を渡す方法が環境変数に限られるケースがあります。この場合,否応なしに環境変数を使うしかありません。こういったケースに対応するため,最近のコマンドラインオプション解析ライブラリでは,環境変数からオプション値を取得する機能がサポートされているものが多く,Smart::Optionsでも対応しています。

use Smart::Options;

$ENV{TEST_FLAG} = 'FLAG VALUE';

Smart::Options->new->env_prefix('TEST')
              ->env('flag')->parse();
# => { 'flag' => 'FLAG VALUE' }

envメソッドを使うと,オプション値が指定されなかった場合に,env_prefixで指定した接頭辞_大文字化したオプション名」の環境変数(上記で言うとTEST_FLAGをオプション値として取得するようになります。

なお,Smart::Optionsでは,コマンドライン引数と環境変数の両方で値が指定されていた場合,コマンドライン引数で渡されたもののほうを優先します。

色付きの出力

diffコマンドなどが良い例ですが,出力結果に適切に色を付けると見分けやすくなります。Perlでターミナルへの出力に色を付けるにはカラー変更のエスケープシーケンスを出力すればよいのですが,Term::ANSIColorを使えばエスケープシーケンスを使わずに色名の指定で同じことをできます。

use Term::ANSIColor;

print color('red') . "この文字は赤く表示されます\n";
print color('red') . "この文字も赤く表示されます\n" . colo
r('reset');
print "この文字は普通の色で表示されます\n";

print color('on_blue white');
print "この文字は青地に白で表示されます\n";
print color('reset');

color関数に色を渡すことで,以降に出力する文字列がその色になります。color('reset')を出力するまで色は変わったままになります。

color('on_blue')のようにon_を色名に付けると背景色の指定になります。それ以外にもbold(強調)⁠blink(点滅)⁠under(下線)などを指定したり,256色に対応した色指定(ansi255)をしたりもできますが,これらは実行される環境によって機能しないこともあります。詳細はTerm::ANSIColorのドキュメントを参照してください。

<続きの(3)こちら。>

WEB+DB PRESS

本誌最新号をチェック!
WEB+DB PRESS Vol.111

2019年6月24日発売
B5判/160ページ
定価(本体1,480円+税)
ISBN978-4-297-10657-7

  • 特集1
    新機能の数々をコミッターが最速解説!
    詳解Rails 6
    新コンポーネント,複数DB対応,並列テスト,オートロード刷新
  • 特集2
    動的かつ高速!
    はじめてのJulia
    科学技術計算のための新言語
  • 特集3
    見える化大作戦
    進捗,成果,無理/ムダ,個人の気持ち……
  • 一般記事
    Elm入門
    型安全な関数型言語によるフロントエンド開発