Perl 「 正規表現 」: split 演算子を利用する (0x7a)

セラ (perlackline)

2014年02月26日 19:00



目次 - Perl Index



Theme



Perl について、復習を兼ねて断片的な情報を掲載して行く連載その 0x7a 回。

Perl 「 正規表現 」( Regular expression ) の split 演算子を利用方法について。




split 演算子の書式



通常 split は関数として紹介されるそうですが、実の所は演算子だとのことです。関数と演算子の違いや、本来演算子であるはずの split が何故関数とされるのか等には今は深入りしません。

split 演算子の書式は次の通りです。


split /PATTERN/,EXPR,LIMIT
split /PATTERN/,EXPR
split /PATTERN/
split


まず基本的な動作として、split 演算子は、「 EXPR 」に指定された文字列を「 PATTERN 」に指定されたパターンで分割し、リストデータとして返します。

分割されたセパレータ以外の部分 = リストになった個々のデータはフィールド ( fields ) と呼ばれます。

「 PATTERN 」には正規表現 ( regexp ) が利用出来ますが、大抵は単純な表現が用いられるとのことです。

「 LIMIT 」は、分割するフィールドの最大数を表す整数を指定します。これは、実際の分割回数よりも 1 つ大きい数字です。

つまり、LIMIT を「 1 」とした場合の分割回数は「 0 」回でフィールドは「 1 」個になり、LIMIT を「 3 」とした場合は分割回数が「 2 」回でフィールドは「 3 」個になります。

「 LIMIT 」を省略した場合、split 演算子は文字列を出来る限り分割します。

「 EXPR 」を省略した場合の分割対象となる文字列は、お馴染みの「 $_ 」に格納された文字列です。

「 /PATTERN/ 」「 EXPR 」「 LIMIT 」を省略して split 演算子を利用した場合、「 EXPR 」には「 $_ 」が「 /PATTERN/ 」には標準のセパレータ「 空白文字 」を利用します。この場合の空文字は「 \s+ 」と同じ様な振る舞いをします。

* ただし「 \s+ 」とは少し違います。違いは以下で確認します。

split 演算子を利用する



例えば、文字列「 Boo Foo Woo 」を分割します。

「 Boo Foo Woo 」は空白文字で分割されているので、文字クラス「 \s 」が利用出来ます。ここでは空白が 1 つなので、空文字「 / / 」としてもかまいません。空白が複数ある可能性がある場合は「 \s+ 」とします。


my $string = "Boo Foo Woo";

my @list = split /\s/, $string;

foreach ( 0..$#list) {
print "\$list[$_] : $list[$_]\n";
}

printf "\n%s and %s and %s is over there.\n", @list;


1 行目で空白文字区切りの文字列「 Boo Foo Woo 」をスカラ変数 $string に代入しています。

3 行目では split 演算子を利用して、配列 @list に分割したリストデータを代入しています。split の PATTERN には文字クラス「 /\s/ 」を、EXPR にはスカラ変数「 $string 」を指定しています。

5 行目の foreach 文は、配列 @list の要素をインデックスとともに表示するものです。これで、split で分割された文字列がどの様に格納されているかが分かります。

9 行目の printf 文は、printf 文の使い方を忘れないために付け足しました。

このプログラムの実行結果は次の通りです。

$list[0] : Boo
$list[1] : Foo
$list[2] : Woo

Boo and Foo and Woo is over there.


EXPR の文字列が「 Boo?Foo/Woo 」の様に数字以外で区切られていた場合は、PATTERN を「 /\W/ 」に変更することで対応出来ます。

EXPR では、「 Boo:Foo:Woo 」の様なリテラルな文字列を指定することも可能です。この場合は PATTERN を「 /:/ 」とすることで「 "Boo", "Foo", "Woo" 」のリストに分割出来ます。

PATTERN ではリテラルに「 ':' 」等、シングル・ダブルいずれのクォーテーションを利用しても分割出来ます。


my @list = split ':', 'Boo:Foo:Woo';


空のフィールドの扱い



例えば「 bibbidi::bobbidi:boo 」という文字列があった場合に、PATTERN 「 /:/ 」で分割するとそれは「 "bibbidi", "", "bobbidi", "boo" 」と 4 つのリストデータが返されます。

「 bibbidi 」の次、2 番目のフィールドが空文字であることに注目します。

では、「 ::bibbidi:bobbidi:boo:: 」という文字列だった場合はどうでしょうか。

予想では「 "", "", "bibbidi", "bobbidi", "boo", "", "" 」を返す様に思いますが、実際は末尾の空文字フィールドは破棄されて「 "", "", "bibbidi", "bobbidi", "boo" 」のリストデータが返されます。

LIMIT に負数 (マイナスの値 : -1 等) を指定した場合、split は極力多くのフィールドに分割しようとするので、末尾の空文字フィールドも残されます。

ただし、セパレータが次の様な空白文字の場合は、末尾だけでなく先頭の空文字も破棄されます。


# 先頭と末尾に空白文字が存在する文字列
$_ = " bibidi bobbidi boo ";

# split 演算子を単体で利用した場合
@list = split;

# または PATTERN に ' '
# または \x20 (ASCII コードで空白を表す) で
# 空文字を指定した場合
@list = split ' ';


実行結果は「 "bibbidi", "bobbidi", "boo" 」となります。先頭と末尾の空白がいずれも破棄されています。これは、Unix のコマンドラインツール「 awk 」をエミュレートした機能なのだそうです。

0x7a -> 0x7b へ



split 演算子の PATTERN には、正規表現でお馴染みのパターンを複雑に指定することも出来るそうです。

しかしながら、「 ( ) 」を使ったグループ化をした場合は、意図した動作と違う動きをする可能性があります。詳しくは、perldocjp の split のページを参照してください。

次回は、split 演算子と相性の良い「 join 関数 」を確認します。

参考情報は書籍「 初めての Perl 第 6 版 」を中心に perldoc, Wikipedia および各 Web サイト。それと詳しい先輩。

目次 - Perl Index




















関連記事