[メモ]Pythonの正規表現

perlだとスムーズに手が動くけど、pythonだと中々手が動かない処理の筆頭が正規表現です。何回調べても全然身に付いてなくて、毎回オーバーヘッドコストが酷いのでメモエントリを書きます。

正規表現と一口に言っても幅広いので、まずは基本的なマッチ処理と置換処理を覚える事にしました。そしてやりたい事をperlで書いたのが以下になります。

#!/usr/bin/perl

use strict;
use warnings;
use Perl6::Say;

my @text = (
	'apple is 2$',
	'orange is 5$',
	'pencil is sold at stationery shop'
);

# ①普通のマッチ
say ($_ =~ /.+ is \d+\$/ ? "OK":"NG") for @text;

# ②マッチ時のフラグ
say ($_ =~ /.+ IS \d+\$/i ? "OK":"NG") for @text;

# ③参照
say join ",", $_ =~ /(.+) is (\d+)\$/ for @text;

# ④置換
foreach my $line (@text) {
	$line =~ s/\$/ dollar/;
	say $line;
}

早速ですが上記プログラムをpythonで書き直したものが以下になります。

webを調べてみると、re.compileで正規表現オブジェクトを作成するのが常套手段な雰囲気なのですが、ここでは手軽さを重視してre.searchを使いました。perlとの一番の違いはマッチング処理の結果としてマッチオブジェクトが返却される事です。必要に応じて、このオブジェクトを操作しマッチした文字列等を取得します。置換処理も同様でre.subを使いました。やはりcompileする必要はありません。

あとpythonだとグルーピングした内容を参照する際に、名前による参照ができるので正規表現のWrite Onlyな性質が少しは軽減できるかもしれませんね。

#!/usr/bin/python
# -*- coding: utf-8 -*-

import re

text  = [
    'apple is 2$',
    'orange is 5$',
    'pencil is sold at stationery shop'
]

# ①普通のマッチ (マッチしない場合はNone)
print [re.search('.+ is \d+\$', s) for s in text]   

# ②マッチ時のフラグ
print [re.search('.+ IS \d+\$', s, re.I) for s in text]

# ③参照 (group(0)はマッチした文字列全体)
items = [re.search('(.+) is (\d+)\$', s) for s in text]
print [(item.group(1), item.group(2)) for item in items if item is not None] 

# ③名前付き参照 (?P< name>正規表現)
items = [re.search('(?P< item>.+) is (?P< price>\d+)\$', s) for s in text]
print [(item.group('item'), item.group('price')) for item in items if item is not None]

# ④置換
print [re.sub('\$', ' dollar', s) for s in text]

re.compileを省ける事が解ったので、大分と心理的な障壁が下がりまして、漸くpythonでも正規表現使えるようになった気がします。

Leave a Reply

Your email address will not be published. Required fields are marked *