miau's blog?

PCRE いろいろ

仕事で PHP の PCRE(Perl Compatible Regular Expressions) に絡んで色々やってたので、メモがてらネタにしてみます。




■\G

同僚が PHP の preg_replace() 内で \G とか使っていた。
今回やりたいのは携帯の絵文字を自前で除去してやる、というもので・・・Perl では確かに文字境界を意識した処理にするために \G を使うのが常套手段。でも PCRE でも \G って使えるんだっけ?ということでマニュアルを当ってみると、

PHP: パターン構文 - Manual

\G
マッチングの開始位置

言明 \G は、カレントのマッチング位置が、 preg_match() 関数の offset 引数に
指定されたマッチングの開始位置である場合に真になります。 offset が非ゼロの
場合は、\A と等価ではありません。PHP 4.3.3 以降で使用可能です。

え。Perl と意味が違うじゃん。(Perl では前回のマッチング末尾)
一応原文も見てみる。

PHP: Pattern Syntax - Manual

\G
first matching position in subject

The \G assertion is true only when the current matching position is at
the start point of the match, as specified by the offset argument of
preg_match(). It differs from \A when the value of offset is non-zero.
It is available since PHP 4.3.3.

日本語訳と同じ内容か・・・。

言語によって正規表現の構文は結構違うんだから、安易に信じちゃダメだってば。

・・・なんてことを考えつつ、簡単に動作確認してみた。あれ?\G の動作 Perl と同じじゃない?
マニュアルが間違ってるパターンか。安易にマニュアル信じちゃダメだな、自分。

■/x

それはまあともかく。実はその人が参考にしてたのはこのページらしく。

■[PC]絵文字の除去 - ハギプラン(愛称:ハプラン)

だいたいこのとおりにコーディングしてたんだけど・・・こういう複雑な正規表現には /x 修飾子つけてほしいな。PCRE でも使えるっぽいし。
自分なりに書き直すとこんな感じ。(あえて定数も展開)

$regex = '{
\G # ※前回のマッチング末尾にマッチ
( # $1: Shift_JIS の文字
(?:
[\x00-\x7F\xA1-\xDF] # 7-bit ASCII & 半角カナ or ...
|
(?:[\x81-\x9F\xE0-\xFC][\x40-\x7E\x80-\xFC]) # 2バイト文字
)*?
)
(?: # 基本絵文字(SJIS)
\xF8[\x9F-\xFC]
|
\xF9[\x40-\x49\x50-\x52\x55-\x57\x5B-\x5E\x72-\x7E\x80-\xB0]
)
|
(?:\xF9[\xB1-\xFC]) # 拡張絵文字(SJIS)
}x';
$string = preg_replace($regex, '$1', $string);

ん?この正規表現間違ってるな。
/\G(A*?)(?:B)|(?:C)/ みたいな構造になってるから、C が文字列先頭か B の直後に現れないとACB みたいな並びの場合うまく除去できないのでは。
/\G(A*?)(?:B|C)/ みたいな構造にしないと。
あと /\G(A*?)(?:B|C)+/ のほうがパフォーマンスがほんの少しいいかも。大差ないはずだけど。

・・・とまあ、見通しいいほうがいいですよね。後で見たときに意味もわかりやすいし。

■ヒアドキュメント(ついで)

今回気づいたけど、PHP のヒアドキュメントは Perl みたいに

$regex = <<<'REGEX'
:
REGEX;

とやって変数展開を抑止することはできないみたい。以前も書いたけど、どうも PHP のヒアドキュメントは貧弱で嫌い。
というか言語として正規表現リテラル(?)がないのが問題か。


(2007-09-14 追記)

ハギプラン(愛称:ハプラン) - 2007-09-04

で、

C が文字列先頭か B の直後に現れないとうまく除去できないのでは。

という部分は間違いだと指摘されたので、一部修正しました。

今回指摘を受けて思ったは、他人のブログに言及したときはやっぱりトラックバック or コメントを残すべきだということ。陰でこっそり指摘する(私がこのアイテムを書いたときにやったのがそれです)のは、議論が進まないので勿体無い。
今までは「どうせ Referer で気づくでしょ」とか「トラックバックやコメントは売名行為っぽくて嫌い」(特に人気サイトにトラックバックする場合)とか思ってたけど、今後はなるべくやります。
posted at 20:30:51 on 2007-07-05 by miau - Category: PHP No Trackbacks - Permalink

TrackBack

このエントリにトラックバックはありません
現在トラックバックは受け付けていません。

Comments

No comments yet

Add Comments

現在コメントは受け付けていません。
お手数ですが、 こちら のコメント欄にでも記載していただければと思います。