Memoize

BasicWerk   EC Support   Technique   Facebook  

20140809223732_regex_single_and_multi_line_mode

regex_single_and_multi_line_mode

 

 

サンプルテキスト

Questions
 
1. 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) は名前的に非常にややこしい。

 

僕はこう覚えてる。

 

  • 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