回答編集履歴

9

a

2016/03/31 10:04

投稿

mpyw
mpyw

スコア5223

test CHANGED
@@ -182,17 +182,7 @@
182
182
 
183
183
  $str = 'I am Tom. He is Mr. Smith.';
184
184
 
185
-
186
-
187
- $sentences = preg_split(
188
-
189
- '/(?:Mr|Mr?s|Dr|Sir|Prof)\.(*SKIP)(*FAIL)|\.\K\s+/',
185
+ $sentences = preg_split('/(?:Mr|Mr?s|Dr|Sir|Prof)\.(*SKIP)(*FAIL)|\.\K\s+/', $str);
190
-
191
- $str, -1, PREG_SPLIT_NO_EMPTY
192
-
193
- );
194
-
195
-
196
186
 
197
187
  var_dump($sentences);
198
188
 
@@ -200,8 +190,6 @@
200
190
 
201
191
  /*
202
192
 
203
-
204
-
205
193
  array(2) {
206
194
 
207
195
  [0]=>
@@ -214,8 +202,6 @@
214
202
 
215
203
  }
216
204
 
217
-
218
-
219
205
  */
220
206
 
221
207
  ```

8

2016/03/31 10:03

投稿

mpyw
mpyw

スコア5223

test CHANGED
@@ -159,3 +159,67 @@
159
159
 
160
160
 
161
161
  という処理を行っています.
162
+
163
+
164
+
165
+ ----
166
+
167
+
168
+
169
+ 【追記】
170
+
171
+
172
+
173
+ コメントにも書きましたが,こちらにも最終目的のコードをシンタックスハイライトをつけて書いておきます.
174
+
175
+
176
+
177
+ ```php
178
+
179
+ <?php
180
+
181
+
182
+
183
+ $str = 'I am Tom. He is Mr. Smith.';
184
+
185
+
186
+
187
+ $sentences = preg_split(
188
+
189
+ '/(?:Mr|Mr?s|Dr|Sir|Prof)\.(*SKIP)(*FAIL)|\.\K\s+/',
190
+
191
+ $str, -1, PREG_SPLIT_NO_EMPTY
192
+
193
+ );
194
+
195
+
196
+
197
+ var_dump($sentences);
198
+
199
+
200
+
201
+ /*
202
+
203
+
204
+
205
+ array(2) {
206
+
207
+ [0]=>
208
+
209
+ string(9) "I am Tom."
210
+
211
+ [1]=>
212
+
213
+ string(16) "He is Mr. Smith."
214
+
215
+ }
216
+
217
+
218
+
219
+ */
220
+
221
+ ```
222
+
223
+
224
+
225
+

7

a

2016/03/31 09:59

投稿

mpyw
mpyw

スコア5223

test CHANGED
@@ -154,6 +154,8 @@
154
154
 
155
155
  3. 現在位置を今マッチさせたバイト列のぶんだけ進める.マッチしていなければ1バイト進める.
156
156
 
157
+ 4. まだ後ろに1バイト以上あれば1に戻る.無ければ終了する.
158
+
157
159
 
158
160
 
159
161
  という処理を行っています.

6

a

2016/03/29 16:33

投稿

mpyw
mpyw

スコア5223

test CHANGED
@@ -152,7 +152,7 @@
152
152
 
153
153
  2. **後ろに「カレー」「ライス」「末尾」のいずれかが来るように**,1バイト以上の可能な限り短いバイト列を探す.マッチしたら置換処理を行う.マッチしなければ3に進む.
154
154
 
155
- 3. 現在位置を今マッチさせたバイト列のぶんだけ進める.
155
+ 3. 現在位置を今マッチさせたバイト列のぶんだけ進める.マッチしていなければ1バイト進める.
156
156
 
157
157
 
158
158
 

5

a

2016/03/29 16:23

投稿

mpyw
mpyw

スコア5223

test CHANGED
@@ -152,7 +152,7 @@
152
152
 
153
153
  2. **後ろに「カレー」「ライス」「末尾」のいずれかが来るように**,1バイト以上の可能な限り短いバイト列を探す.マッチしたら置換処理を行う.マッチしなければ3に進む.
154
154
 
155
- 3. 現在位置を今マッチさせた文字列のぶんだけ進める.
155
+ 3. 現在位置を今マッチさせたバイト列のぶんだけ進める.
156
156
 
157
157
 
158
158
 

4

a

2016/03/29 16:21

投稿

mpyw
mpyw

スコア5223

test CHANGED
@@ -13,10 +13,6 @@
13
13
  ```php
14
14
 
15
15
  <?php
16
-
17
-
18
-
19
- header('Content-Type: text/plain; charset=UTF-8');
20
16
 
21
17
 
22
18
 
@@ -37,10 +33,6 @@
37
33
  ```php
38
34
 
39
35
  <?php
40
-
41
-
42
-
43
- header('Content-Type: text/plain; charset=UTF-8');
44
36
 
45
37
 
46
38
 
@@ -106,7 +98,7 @@
106
98
 
107
99
 
108
100
 
109
- `strtr` `preg_replace (単一の正規表現で処理)` においては一度置換したところを次回の置換対象から外してくれますが, `str_replace` `preg_replace (複数の正規表現で処理)` においては全く考慮してくれません. 速度面においても,僅かな違いですが,一般的には速い順に
101
+ **`strtr` `preg_replace (単一の正規表現で処理)` においては一度置換したところを次回の置換対象から外してくれますが, `str_replace` `preg_replace (複数の正規表現で処理)` においては全く考慮してくれません. **速度面においても,僅かな違いですが,一般的には速い順に
110
102
 
111
103
 
112
104
 
@@ -124,17 +116,13 @@
124
116
 
125
117
 
126
118
 
127
- また正規表現の高度なテクニックですが,バックトラッキングコントロールを使うとまさに「あるバイト列以外のバイト列を直接マッチさせることもできます.
119
+ また正規表現の高度なテクニックですが,バックトラッキングコントロールを使うとまさに**「あるバイト列以外のバイト列」**を直接マッチさせることもできます.
128
120
 
129
121
 
130
122
 
131
123
  ```php
132
124
 
133
125
  <?php
134
-
135
-
136
-
137
- header('Content-Type: text/plain; charset=UTF-8');
138
126
 
139
127
 
140
128
 

3

a

2016/03/29 16:20

投稿

mpyw
mpyw

スコア5223

test CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
 
4
4
 
5
- -[マルチバイト文字を扱う際に気をつけること](http://qiita.com/mpyw/items/a8dba1b80fe68523b8eb)
5
+ - [マルチバイト文字を扱う際に気をつけること](http://qiita.com/mpyw/items/a8dba1b80fe68523b8eb)
6
6
 
7
7
 
8
8
 

2

一応s修飾子を追加

2016/03/29 16:17

投稿

mpyw
mpyw

スコア5223

test CHANGED
@@ -1,4 +1,36 @@
1
- 既に回答にありますが,`preg_replace`あるいは`preg_replace_callback`を使って文字列置換済むのであればそれが一番簡単です.正規表現無に書ける範囲`str_replace``strtr`を使うほうがよでしょう.但しこれらに微妙な違いがあるので注意してください.以下を実行るとわかります.
1
+ まず前提として,この回答には文字列ではなく**バイト列**という表記にします.日本語を相手に本当に1文字という見てくるのは`u`修飾子をつけた`preg_*`系の関数,あるいは文字コードをUTF-8として正し指定た`mb_*`系の関数のです.残の関数は全てバイト単位で計算します.
2
+
3
+
4
+
5
+ -[マルチバイト文字を扱う際に気をつけること](http://qiita.com/mpyw/items/a8dba1b80fe68523b8eb)
6
+
7
+
8
+
9
+ 本題に入ります.既に回答にありますが,**除外したいバイト列を空白に置換して残ったバイト列を得る**というアプローチにて`preg_replace`あるいは`preg_replace_callback`を使って済むのであればそれが一番簡単です.正規表現無しでも簡単に書ける範囲であれば`str_replace`や`strtr`を使うほうがよいでしょう.なお文字コードがUTF-8である場合は,正規表現の文字クラス`[]`を使わない限り,「文字列=バイト列」のように扱っても正しく動作します.このことは上にリンクしたQiitaの記事でも解説しています.
10
+
11
+
12
+
13
+ ```php
14
+
15
+ <?php
16
+
17
+
18
+
19
+ header('Content-Type: text/plain; charset=UTF-8');
20
+
21
+
22
+
23
+ $str = 'ライスパスタカレーパスタドリア';
24
+
25
+
26
+
27
+ echo str_replace('パスタ', '', $str), "\n"; // ライスカレードリア
28
+
29
+ ```
30
+
31
+
32
+
33
+ 但しこれらには,複数の置換を同時に行う際に微妙な違いがあるので注意してください.以下を実行してみるとわかります.
2
34
 
3
35
 
4
36
 
@@ -18,6 +50,8 @@
18
50
 
19
51
  print_r([
20
52
 
53
+
54
+
21
55
  'str_replace' => str_replace(
22
56
 
23
57
  ['カレーライス', 'カレー', 'ライス'],
@@ -26,7 +60,9 @@
26
60
 
27
61
  $str
28
62
 
29
- ),
63
+ ), // 【ライス】パスタ【ライス】【【カレー】【ライス】】【カレー】ドリア
64
+
65
+
30
66
 
31
67
  'strtr' => strtr($str, [
32
68
 
@@ -36,7 +72,9 @@
36
72
 
37
73
  'ライス' => '【ライス】',
38
74
 
39
- ]),
75
+ ]), // 【ライス】パスタ【ライス】【カレーライス】【カレー】ドリア
76
+
77
+
40
78
 
41
79
  'preg_replace (複数の正規表現で処理)' => preg_replace(
42
80
 
@@ -46,7 +84,9 @@
46
84
 
47
85
  $str
48
86
 
49
- ),
87
+ ), // 【ライス】パスタ【ライス】【【カレー】【ライス】】【カレー】ドリア
88
+
89
+
50
90
 
51
91
  'preg_replace (単一の正規表現で処理)' => preg_replace(
52
92
 
@@ -56,7 +96,9 @@
56
96
 
57
97
  $str
58
98
 
59
- ),
99
+ ), // 【ライス】パスタ【ライス】【カレーライス】【カレー】ドリア
100
+
101
+
60
102
 
61
103
  ]);
62
104
 
@@ -64,7 +106,25 @@
64
106
 
65
107
 
66
108
 
109
+ `strtr` `preg_replace (単一の正規表現で処理)` においては一度置換したところを次回の置換対象から外してくれますが, `str_replace` `preg_replace (複数の正規表現で処理)` においては全く考慮してくれません. 速度面においても,僅かな違いですが,一般的には速い順に
110
+
111
+
112
+
113
+ 1. `str_replace`
114
+
115
+ 2. `strtr` (実はもう1つ使い方があるがこの例のように連想配列で置換する場合)
116
+
117
+ 3. `preg_replace (単一の正規表現で処理)`
118
+
119
+ 4. `preg_replace (複数の正規表現で処理)`
120
+
121
+
122
+
123
+ として差がつくと思うので,書きやすさも考慮して適宜使い分けてください.
124
+
125
+
126
+
67
- 正規表現の高度なテクニックですが,バックトラッキングコントロールを使うとまさにabc」と言う塊以外の文字を直接マッチさせることもできます.
127
+ また正規表現の高度なテクニックですが,バックトラッキングコントロールを使うとまさに「あるバイト列以外のバイト列を直接マッチさせることもできます.
68
128
 
69
129
 
70
130
 
@@ -82,18 +142,30 @@
82
142
 
83
143
 
84
144
 
85
- print_r([
145
+ echo preg_replace(
86
146
 
87
- 'preg_replace (バックトッキングコントロ)' => preg_replace(
147
+ '/(?:カレー|イス)(*SKIP)(*FAIL)|.+?(?=カレ|ライス|\z)/s',
88
148
 
89
- '/(?:カレー|ライス)(*SKIP)(*FAIL)|.+?(?=カレー|ライス|\z)/',
149
+ '【$0】',
90
150
 
91
- '【$0】',
151
+ $str
92
152
 
93
- $str
153
+ ), "\n"; // ライス【パスタ】ライスカレーライスカレー【ドリア】
94
-
95
- ),
96
-
97
- ]);
98
154
 
99
155
  ```
156
+
157
+
158
+
159
+ 上記の例では
160
+
161
+
162
+
163
+ 1. まず現在位置から「カレー」「ライス」いずれかにマッチするバイト列を探す.**マッチしたら何も無かったことにして3に進む.**マッチしなければ2に進む.
164
+
165
+ 2. **後ろに「カレー」「ライス」「末尾」のいずれかが来るように**,1バイト以上の可能な限り短いバイト列を探す.マッチしたら置換処理を行う.マッチしなければ3に進む.
166
+
167
+ 3. 現在位置を今マッチさせた文字列のぶんだけ進める.
168
+
169
+
170
+
171
+ という処理を行っています.

1

修正

2016/03/29 16:16

投稿

mpyw
mpyw

スコア5223

test CHANGED
@@ -42,7 +42,7 @@
42
42
 
43
43
  ['/カレーライス/', '/カレー/', '/ライス/'],
44
44
 
45
- ['【カレーライス】', '【カレー】', '【ライス】'],
45
+ '【$0】',
46
46
 
47
47
  $str
48
48