Memoize |
BasicWerk
EC Support
Technique
Facebook
|
20140809223732_regex_single_and_multi_line_mode |
regex_single_and_multi_line_mode
サンプルテキスト Questions1. What is your name? 2. How old are you? 3. What is your job? 4. So what?
サンプルスクリプト Q_dig.pl#! /usr/bin/perl use warnings; use strict; # 一気読みモード $/ = undef; # ファイルの全行を一気に読んで閉じる my $content = <>; # regex here print "$content\n";
スクリプトの準備 % chmod a+x Q_dig.pl
正規表現のシングルラインモード(s)、マルチラインモード(m) は名前的に非常にややこしい。
僕はこう覚えてる。
実際に試してみよう。
#! /usr/bin/perl use warnings; use strict; # 一気読みモード $/ = undef; # ファイルの全行を一気に読んで閉じる my $content = <>; # regex here $content =~ s/^.+$/aaa/; print "$content\n";
この正規表現を実行してもファイルの中身は何も置換されない。
% Q_dig.pl Questions 1. What is your name? 2. How old are you? 3. What is your job? 4. So what?
なぜか? それは、フラグが一つも立っていないデフォルトの状態では、「^」は $content に格納された文字列の先頭にマッチし、「$」は文字列の末尾にマッチしようとする。 つまりこの場合ファイルの先頭と末尾だ。 ところが、「.」はデフォルトでは改行文字にマッチしない。 だから「^.+」という正規表現が「1. What is your name?」までは成功するが、「.」が改行文字に出くわした時点で失敗し、「$」は自分がマッチするところまで辿りつけないので、正規表現全体が失敗する(故に置換が実行されない)。
では、正規表現をこう書き換えてみよう。 # regex here $content =~ s/^.+$/aaa/s; ... % Q_dig.pl Questions aaa s フラグを立てたことで「.」が改行文字にもマッチするようになり、「$」がめでたく文末にマッチできるので、文字列全体が「aaa」に置換される。 これがシングルラインモードだ。
では上の正規表現の s フラグを m フラグに変えてみよう。 # regex here $content =~ s/^.+$/aaa/m; ... % Q_dig.pl Questions aaa 2. How old are you? 3. What is your job? 4. So what? 「^」と「$」が各行の先頭と末尾にマッチするようになる。 g フラグを付けてみるとよく分かる。 # regex here $content =~ s/^.+$/aaa/mg; ... % Q_dig.pl Questions aaa aaa aaa aaa これがマルチラインモードである。
マルチラインモードのときに文字列全体の先頭と末尾にマッチさせる必要があるときは「\A」と「\Z」を使う。 # regex here # 先頭の1行だけを aaa に $content =~ s/\A.+$/aaa/m; # 最後の1行だけを zzz に $content =~ s/^.+\Z/zzz/m; ... % Q_dig.pl Questions aaa 2. How old are you? 3. What is your job? zzz
|
© Shin Nakamura/BasicWerk 2014 |