Perl入門ゼミ

テキスト処理、Linuxサーバー管理、Web開発ならPerl
  1. Perl
  2. ファイル入出力
  3. here

オプションを指定できるフィルタプログラムを書く

コマンドライン引数で、オプションを指定できるフィルタプログラムを書いてみます。オプションに指定できるのは、切り出す列の位置と区切り文字です。

use strict;
use warnings;

# コマンドラインオプションを扱うためのモジュール
use Getopt::Long 'GetOptions';

# Unix風のフィルタプログラミングを記述する。
# 今回はカンマ区切りの文字列の一列目を取り出すフィルタプログラムです。

# コマンドラインオプションが指定されなかった場合のデフォルト値
my $col = 1;
my $sep = ',';

# コマンドラインオプションを受け取る
GetOptions(
  'col=i' => \$col,
  'sep=s' => \$sep,
);

# . など正規表現で特別な意味を持つ文字が指定された
# 場合でも正しく動くように文字列をエスケープ
$sep = quotemeta($sep); 

# 特殊な行入力演算子
while (<>) { 
  # chomp関数は引数を省略したときは、$_が対象とされる。
  chomp;
  
  # splitの第3引数の-1は、最終列が空文字であった場合に
  # も正しく動くようにするために指定
  # split関数がリストを返すので、必要な部分だけ
  # 配列スライスで取得
  my $item = (split( /$sep/, $_, -1))[$col - 1];
  print $item . "\n";
}

(参考)正規表現

以下は、読み込み用のファイルです。

masao:10:Japan
taro:20:USA
rika:38:France

コード解説

(1)コマンドラインオプションの指定方法

use Getopt::Long;

Getopt::Longを使うと、コマンドラインオプションを簡単に指定できます。コマンドラインオプションを指定する場合は以下のようにします。

コマンドライン引数についてわからない場合は、先に次の記事をご覧ください。

# 指定方法1( --name val 形式)
perl スクリプト名 --col 1 --sep : ファイル名

# 指定方法2( --name=val 形式)
perl スクリプト名 --col=1 --sep=: ファイル名

# 指定方法3( 省略形式 )
perl スクリプト名 -c1 -s: ファイル名

(2)GetOptions関数

GetOption関数は、コマンドラインオプションの受け取りを簡単にするための関数です。use Getopt::Long したときに、インポートされます。

以下は書き方のサンプルです。

# コマンドラインオプションが指定されなかった場合のデフォルト値
my $col = 1;
my $sep = ',';

# コマンドラインオプションを受け取る
GetOptions(
  'col=i' => \$col,
  'sep=s' => \$sep,
);

まず、コマンドラインオプションのデフォルト値を設定します。

次にGetOption関数を呼び出して指定したいオプションの数だけ

'オプション名=値の種類' => 変数へのリファレンス

という記述を並べます。値の種類には、文字列を表す s 数値を表す i などを指定できます。

(3) whileループでの行読み込みの改良

while (<>) {
  chomp;
  my $item = (split(/$sep/, $_, -1))[$col - 1];
  print $item,"\n";
}

whileでのループ処理については、次の記事をご覧ください。

(3)-1 $_の省略

chomp;

chomp関数で引数を省略すると作用する対象は特殊変数「$_」になります。Perlには、引数を省略すると$_に作用する関数が他にもたくさんあります。

(3)-2 split関数の第3引数に-1を指定

split(/$sep/, $_, -1)

split関数の第3引数を省略すると要素の最後が空白の場合は、最後の空文字が無視されてしまいます。(hutaさんに指摘されました。)

taro,10,

を読み込んだ場合、ほしいのは

('taro', 10, '')

というリストであるのに

('taro', 10)

を取得してしまいます。これを解決するために、splitの第3引数に、-1を与えることで最後の空文字を認識させることができます。

(3)-3 配列スライスで指定した要素だけを取得

my $item = (split(/$sep/, $_, -1))[$col - 1];

splitは、リストを返すので配列スライスで、指定した要素だけを取得しています。

Qiitaで
「3分間Perlテキストクッキング」
という連載を始めました。
テキスト処理を題材にして、3分くらいで読める分量で、書いていきます。
文字コード、テキストデータ、コンピュータにおけるテキストの扱いなど、ソフトウェアの基礎の話題も
3分間Perlテキストクッキング