本連載では第一線のPerlハッカーが回替わりで執筆していきます。今回のハッカーはPerl入学式のサポーターで知られる尾形鉄次さんで、
本稿のサンプルコードは、use strict;
とuse warnings;
は省略しています。全文は、
正規表現は文字列処理の強い味方
Perlは文字列処理に強いと言われていますが、
一方で、
Perl正規表現の基本
正規表現の話題は広範です。紙幅の都合もあり、
メタ文字 | 説明 |
---|---|
. | 任意の1文字にマッチする |
[■] | 文字クラス。リスト■の中にある任意の1文字にマッチする |
[^■] | 否定の文字クラス。リスト■の中にない任意の1文字にマッチする |
●? | 正規表現●が0個もしくは1個存在する |
●* | 正規表現●が0個もしくは1個以上存在する |
●+ | 正規表現●が1個以上存在する |
●*? | ●*と同じ意味だが、 |
(●) | グループを作る。正規表現●にマッチした場合、 |
(?:●) | グループを作るが、 |
●|◎ | 左右の正規表現●◎のどちらかにマッチする。上記のグループの中で使われることが多い |
^● | 正規表現●の冒頭にある場合、 |
●$ | 正規表現●の末尾にある場合、 |
\s | 空白、 |
\d | 数値1文字を表す |
\b | 単語境界を表す |
表1に登場する用語を説明します。対象文字列が正規表現で表される場合、$1、
に格納されます。
日本語文字列と正規表現
標準のPerlでは、
Perlで日本語の1文字を正しく認識する
日本語文字列を含むマルチバイト文字列をPerlで正しく扱うには、
ソースコード内に直接書かれた文字列リテラルを一括でPerlの内部文字列に変換するには、utf8
プラグマを宣言します。
外部との入出力においてバイト列とPerlの内部文字列を相互変換するには、print
関数などでの画面出力時にPerlIOを使用して自動的にバイト列への変換を行うbinmode STDOUT, 'utf8'
命令は、utf8
プラグマ宣言時に便利です。
上記を怠った場合も、
utf8
プラグマ宣言によって、"こんにちは"
が5文字のPerlの内部文字列となり、$len
は5
になります。binmode STDOUT, 'utf8'
命令によって、
length
関数は1バイトを1文字と解釈して、$len
は15
となります
まとめると、
Perlの正規表現で日本語の1文字に正しくマッチする
バイト列とPerlの内部文字列の違いは、length
だけでなく1文字を認識しようとするPerlでの指示全般に言えます。正規表現のメタ文字も例外ではなく、[■]
が影響を受けます。
$week1
と$week2
は文字化けするのに対し、$week3
は意図どおり"木"
となります。
"木"
が文字どおりの1文字ではなく3バイト分のUTF-8のバイト列"\xE6\x9C\xA8"
として評価され、/(.)曜日/
でキャプチャされるものは印字不可能な1バイト文字"\xA8"
です。[月火水木金土日]
の中には21バイトの文字があると評価されますが、"\xA8"
がキャプチャされます。
(●|◎)
には1文字を評価する意図がないためです。
上記の例においてutf8
プラグマ宣言がある場合、"木"
がキャプチャされます。
新規で書くPerlプログラムではutf8
プラグマを宣言して、
正規表現にまつわる演算子
Perlには正規表現にまつわるさまざまな演算子があります。お馴染みかもしれませんが、
m//演算子──検索を行う
まずは、m//
です。m//
のm
はマッチm//
はマッチ演算子とも呼ばれます。
文字列が代入された変数$str
に対し、●
にマッチするパターンがあるかを検索したい場合、m//
と二項演算子=~
を使って$str=~ m/●/
と書きます。マッチするパターンがある場合に$str =~ m/●/
は真、if
文の条件部分で使うことが多いです。
m//
ではなくm||
などのスラッシュ以外の区切り記号の選択については後述しますが、m
記号を省略できるというルールがあります。上記の$str =~ m/木曜日/
の場合、$str=~ /木曜日/
とm
を省略できます。
本稿でも、m
を省略しますm
が省略されている場合でも、m//
と書いています。
s///演算子──置換を行う
マッチした箇所を別の文字列に置換する場合、 文字列変数 通常、 この よく使われる修飾子については後述します。 特殊変数 この直接書かれない 上記の例は、 また、 対となる記号がある括弧類を区切り記号にすることも可能で、 <続きの 2022年8月24日発売s///
を使います。s///
のs
は代用を意味するsubstitutionの頭文字です。
$str
と正規表現●
があり、■
で置換する場合、s///
と=~
を使って$str =~ s/●/■/
と書きます。s///
と右側にg
を付けます。g
は大域を意味するglobalの頭文字です。g
に代表される、/g
のように書きます。特殊変数$_──正規表現演算子のデフォルトの処理対象
m//
やs///
が二項演算子=~
を伴わない場合、$_
とのマッチを試みます。つまり、m//
やs///
の左側に$_ =~
が省略されたとみなされます。$_
は、while(<>)
構文で1行の文字列が格納される変数など、$_
を活用して簡潔なプログラムを書く方針には賛否両論ありますが、#
開始のコメント行を除いて表示します。while(<>)
によって、$_
に標準入力の1行が順番に代入されます。標準入力の末尾に到達すると、<>は
偽と評価されてwhile
文から抜けます。/\s*#/
はコメント行、/^\s*$/
は空行を表していて、m//
は=~
を伴っていないので、$_
とマッチを試みます。print
が$_
を出力文字列とする性質を利用しています。区切り記号の変更
m//
の解説時に少し触れましたが、m//
、s///
は区切り記号をスラッシュ/
以外から選ぶことができます。m//
の区切り記号として縦線|
を選んでいます。m/(https?:\/\/\S+)/
のようにバックスラッシュを使ってエスケープする必要があります。正規表現で特定の記号群を多用する場合、s///
の場合も、s|||
のように変更できます。m{}
、m[]
、s{}{}
、s[][]
と直感的に書くことができます。波括弧{}
は正規表現のメタ文字本誌最新号をチェック!
WEB+DB PRESS Vol.130
B5判/
定価1,628円
ISBN978-4-297-13000-8
イミュータブルデータモデルで始める
実践データモデリング
業務の複雑さをシンプルに表現!
いまはじめるFlutter
iOS/
作って学ぶWeb3
ブロックチェーン、