Perlの正規表現で複数行にマッチさせる方法
Perlの正規表現で複数行にマッチさせる方法を紹介します。
1.改行を含めてマッチさせる
複数行にマッチさせるには、単に改行文字「\r\n」や「\n」を正規表現に含めるだけです。
ですが、そもそも対象のテキストに改行が含まれていることが前提になります。
次のように、ファイルをオープンしてファイルハンドルをwhile文でループさせるだけでは改行は含まれません。ファイルハンドルに1行ずつ配列として読み込まれるためです。
open my $fh, $file;
while (<$fh>) {
# ...
}
改行にマッチさせる正規表現は知っていても、ファイルを一括読み込みさせる方法が分からない方は、3項に示す一括読み込みを行ってください。
2.改行を含めてマッチさせる(他の方法)
1項の他に、改行を含めたマッチ方法としては、mオプションまたはsオプションの利用があります。
sオプション(または1行モード(Single line mode))はワイルドカードのピリオド「.」が改行にもマッチするようになります。
$str =~ /~/s;
例として、sオプションを使って以下の複数行テキストの中にある赤色部分の3行を取り出してみます。
AUTHOR: mtbook
TITLE: シンポジウム2010
BASENAME: 2010
STATUS: Publish
ALLOW COMMENTS: 1
CONVERT BREAKS: __default__
CATEGORY: イベント
DATE: 04/03/2012 05:44:32 PM
この場合、次のように書くとよいでしょう。
#!/usr/bin/perl
use strict;
my $data = <<EOF;
AUTHOR: mtbook
TITLE: シンポジウム2010
BASENAME: 2010
STATUS: Publish
ALLOW COMMENTS: 1
CONVERT BREAKS: __default__
CATEGORY: イベント
DATE: 04/03/2012 05:44:32 PM
EOF
if ($data =~ /.*(BASENAME: 2010.STATUS: Publish.ALLOW COMMENTS: 1\n).*/s) {
print $1;
}
mオプション(または複数行モード(Multiple line mode))は、文字列を複数行として扱えるようになります。つまり、正規表現に改行「\n」を記述することで改行にマッチするようになります。
$str =~ /~/m;
なお、mオプションは正規表現中に「^」や「$」を使って先頭や末尾を指定しないとマッチしません。
2.改行を含めてマッチさせる処理を繰り返す
改行を含めてマッチさせる処理を繰り返すには、パターンマッチ演算子にgオプションをつけて、while文で繰り返すだけです。
以下はmオプションを利用した例です。
#!/usr/bin/perl
use strict;
my $file = shift;
open my $fh, $file;
my $content = do { local $/; <$fh> };
while ($content =~ /(^BASENAME: .*$)/gm) {
print $1;
}
このコードに次のようなテキストファイルを読み込ませれば、指定したパターンにマッチしなくなくなるまで繰り返し処理してくれます。
--------
AUTHOR: mtbook
TITLE: シンポジウム2010
BASENAME: 2010
STATUS: Publish
ALLOW COMMENTS: 1
CONVERT BREAKS: __default__
CATEGORY: イベント
DATE: 04/03/2012 05:44:32 PM
--------
AUTHOR: mtbook
TITLE: ホームページリニューアル
BASENAME: post
STATUS: Publish
ALLOW COMMENTS: 1
CONVERT BREAKS: __default__
CATEGORY: お知らせ
DATE: 03/17/2012 05:43:43 PM
--------
AUTHOR: mtbook
TITLE: 業務提携に関するお知らせ
BASENAME: post-8
STATUS: Publish
ALLOW COMMENTS: 1
CONVERT BREAKS: __default__
CATEGORY: お知らせ
DATE: 08/10/2013 05:46:00 PM
--------
3.複数行を一括読み込みする
外部ファイルを複数行として処理するためには、2項で示したように読み込んだファイルを一括読み込みさせる必要があります。
open my $fh, $file;
my $content = do { local $/; <$fh> };
「$/」は特殊変数で、改行区切りを一時的に無効にする機能があります。そして1行分のデータを読み込みます。
2013.05.28
本文を修正しました。
- Perlの正規表現で文字列マッチを繰り返し判定する方法
- Perlの正規表現で条件分岐する方法
- 正規表現の最短マッチと最長マッチについて
- Perlの正規表現で繰り返し置換する方法
- Perlの正規表現で制御文字を削除する