まず前提として,この回答においては文字列ではなくバイト列という表記にします.日本語を相手にしても本当に1文字という単位で見てくれるのはu
修飾子をつけたpreg_*
系の関数,あるいは文字コードをUTF-8として正しく指定したmb_*
系の関数のみです.残りの関数は全てバイト単位で計算します.
本題に入ります.既に回答にありますが,除外したいバイト列を空白に置換して残ったバイト列を得るというアプローチにてpreg_replace
あるいはpreg_replace_callback
を使って済むのであればそれが一番簡単です.正規表現無しでも簡単に書ける範囲であればstr_replace
やstrtr
を使うほうがよいでしょう.なお文字コードがUTF-8である場合は,正規表現の文字クラス[]
を使わない限り,「文字列=バイト列」のように扱っても正しく動作します.このことは上にリンクしたQiitaの記事でも解説しています.
php
1<?php
2
3$str = 'ライスパスタカレーパスタドリア';
4
5echo str_replace('パスタ', '', $str), "\n"; // ライスカレードリア
但しこれらには,複数の置換を同時に行う際に微妙な違いがあるので注意してください.以下を実行してみるとわかります.
php
1<?php
2
3$str = 'ライスパスタライスカレーライスカレードリア';
4
5print_r([
6
7 'str_replace' => str_replace(
8 ['カレーライス', 'カレー', 'ライス'],
9 ['【カレーライス】', '【カレー】', '【ライス】'],
10 $str
11 ), // 【ライス】パスタ【ライス】【【カレー】【ライス】】【カレー】ドリア
12
13 'strtr' => strtr($str, [
14 'カレーライス' => '【カレーライス】',
15 'カレー' => '【カレー】',
16 'ライス' => '【ライス】',
17 ]), // 【ライス】パスタ【ライス】【カレーライス】【カレー】ドリア
18
19 'preg_replace (複数の正規表現で処理)' => preg_replace(
20 ['/カレーライス/', '/カレー/', '/ライス/'],
21 '【$0】',
22 $str
23 ), // 【ライス】パスタ【ライス】【【カレー】【ライス】】【カレー】ドリア
24
25 'preg_replace (単一の正規表現で処理)' => preg_replace(
26 '/カレーライス|カレー|ライス/',
27 '【$0】',
28 $str
29 ), // 【ライス】パスタ【ライス】【カレーライス】【カレー】ドリア
30
31]);
**strtr
preg_replace (単一の正規表現で処理)
においては一度置換したところを次回の置換対象から外してくれますが, str_replace
preg_replace (複数の正規表現で処理)
においては全く考慮してくれません. **速度面においても,僅かな違いですが,一般的には速い順に
str_replace
strtr
(実はもう1つ使い方があるがこの例のように連想配列で置換する場合)
preg_replace (単一の正規表現で処理)
preg_replace (複数の正規表現で処理)
として差がつくと思うので,書きやすさも考慮して適宜使い分けてください.
また正規表現の高度なテクニックですが,バックトラッキングコントロールを使うとまさに**「あるバイト列以外のバイト列」**を直接マッチさせることもできます.
php
1<?php
2
3$str = 'ライスパスタライスカレーライスカレードリア';
4
5echo preg_replace(
6 '/(?:カレー|ライス)(*SKIP)(*FAIL)|.+?(?=カレー|ライス|\z)/s',
7 '【$0】',
8 $str
9), "\n"; // ライス【パスタ】ライスカレーライスカレー【ドリア】
上記の例では
- まず現在位置から「カレー」「ライス」いずれかにマッチするバイト列を探す.**マッチしたら何も無かったことにして3に進む.**マッチしなければ2に進む.
- 後ろに「カレー」「ライス」「末尾」のいずれかが来るように,1バイト以上の可能な限り短いバイト列を探す.マッチしたら置換処理を行う.マッチしなければ3に進む.
- 現在位置を今マッチさせたバイト列のぶんだけ進める.マッチしていなければ1バイト進める.
- まだ後ろに1バイト以上あれば1に戻る.無ければ終了する.
という処理を行っています.
【追記】
コメントにも書きましたが,こちらにも最終目的のコードをシンタックスハイライトをつけて書いておきます.
php
1<?php
2
3$str = 'I am Tom. He is Mr. Smith.';
4$sentences = preg_split('/(?:Mr|Mr?s|Dr|Sir|Prof)\.(*SKIP)(*FAIL)|\.\K\s+/', $str);
5var_dump($sentences);
6
7/*
8array(2) {
9 [0]=>
10 string(9) "I am Tom."
11 [1]=>
12 string(16) "He is Mr. Smith."
13}
14*/
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/03/31 03:40
2016/03/31 09:46
2016/03/31 10:04 編集