質問するログイン新規登録

回答編集履歴

9

a

2016/03/31 10:04

投稿

mpyw
mpyw

スコア5223

answer CHANGED
@@ -90,23 +90,16 @@
90
90
  <?php
91
91
 
92
92
  $str = 'I am Tom. He is Mr. Smith.';
93
-
94
- $sentences = preg_split(
95
- '/(?:Mr|Mr?s|Dr|Sir|Prof)\.(*SKIP)(*FAIL)|\.\K\s+/',
93
+ $sentences = preg_split('/(?:Mr|Mr?s|Dr|Sir|Prof)\.(*SKIP)(*FAIL)|\.\K\s+/', $str);
96
- $str, -1, PREG_SPLIT_NO_EMPTY
97
- );
98
-
99
94
  var_dump($sentences);
100
95
 
101
96
  /*
102
-
103
97
  array(2) {
104
98
  [0]=>
105
99
  string(9) "I am Tom."
106
100
  [1]=>
107
101
  string(16) "He is Mr. Smith."
108
102
  }
109
-
110
103
  */
111
104
  ```
112
105
 

8

2016/03/31 10:03

投稿

mpyw
mpyw

スコア5223

answer CHANGED
@@ -78,4 +78,35 @@
78
78
  3. 現在位置を今マッチさせたバイト列のぶんだけ進める.マッチしていなければ1バイト進める.
79
79
  4. まだ後ろに1バイト以上あれば1に戻る.無ければ終了する.
80
80
 
81
- という処理を行っています.
81
+ という処理を行っています.
82
+
83
+ ----
84
+
85
+ 【追記】
86
+
87
+ コメントにも書きましたが,こちらにも最終目的のコードをシンタックスハイライトをつけて書いておきます.
88
+
89
+ ```php
90
+ <?php
91
+
92
+ $str = 'I am Tom. He is Mr. Smith.';
93
+
94
+ $sentences = preg_split(
95
+ '/(?:Mr|Mr?s|Dr|Sir|Prof)\.(*SKIP)(*FAIL)|\.\K\s+/',
96
+ $str, -1, PREG_SPLIT_NO_EMPTY
97
+ );
98
+
99
+ var_dump($sentences);
100
+
101
+ /*
102
+
103
+ array(2) {
104
+ [0]=>
105
+ string(9) "I am Tom."
106
+ [1]=>
107
+ string(16) "He is Mr. Smith."
108
+ }
109
+
110
+ */
111
+ ```
112
+

7

a

2016/03/31 09:59

投稿

mpyw
mpyw

スコア5223

answer CHANGED
@@ -76,5 +76,6 @@
76
76
  1. まず現在位置から「カレー」「ライス」いずれかにマッチするバイト列を探す.**マッチしたら何も無かったことにして3に進む.**マッチしなければ2に進む.
77
77
  2. **後ろに「カレー」「ライス」「末尾」のいずれかが来るように**,1バイト以上の可能な限り短いバイト列を探す.マッチしたら置換処理を行う.マッチしなければ3に進む.
78
78
  3. 現在位置を今マッチさせたバイト列のぶんだけ進める.マッチしていなければ1バイト進める.
79
+ 4. まだ後ろに1バイト以上あれば1に戻る.無ければ終了する.
79
80
 
80
81
  という処理を行っています.

6

a

2016/03/29 16:33

投稿

mpyw
mpyw

スコア5223

answer CHANGED
@@ -75,6 +75,6 @@
75
75
 
76
76
  1. まず現在位置から「カレー」「ライス」いずれかにマッチするバイト列を探す.**マッチしたら何も無かったことにして3に進む.**マッチしなければ2に進む.
77
77
  2. **後ろに「カレー」「ライス」「末尾」のいずれかが来るように**,1バイト以上の可能な限り短いバイト列を探す.マッチしたら置換処理を行う.マッチしなければ3に進む.
78
- 3. 現在位置を今マッチさせたバイト列のぶんだけ進める.
78
+ 3. 現在位置を今マッチさせたバイト列のぶんだけ進める.マッチしていなければ1バイト進める.
79
79
 
80
80
  という処理を行っています.

5

a

2016/03/29 16:23

投稿

mpyw
mpyw

スコア5223

answer CHANGED
@@ -75,6 +75,6 @@
75
75
 
76
76
  1. まず現在位置から「カレー」「ライス」いずれかにマッチするバイト列を探す.**マッチしたら何も無かったことにして3に進む.**マッチしなければ2に進む.
77
77
  2. **後ろに「カレー」「ライス」「末尾」のいずれかが来るように**,1バイト以上の可能な限り短いバイト列を探す.マッチしたら置換処理を行う.マッチしなければ3に進む.
78
- 3. 現在位置を今マッチさせた文字列のぶんだけ進める.
78
+ 3. 現在位置を今マッチさせたバイト列のぶんだけ進める.
79
79
 
80
80
  という処理を行っています.

4

a

2016/03/29 16:21

投稿

mpyw
mpyw

スコア5223

answer CHANGED
@@ -7,8 +7,6 @@
7
7
  ```php
8
8
  <?php
9
9
 
10
- header('Content-Type: text/plain; charset=UTF-8');
11
-
12
10
  $str = 'ライスパスタカレーパスタドリア';
13
11
 
14
12
  echo str_replace('パスタ', '', $str), "\n"; // ライスカレードリア
@@ -19,8 +17,6 @@
19
17
  ```php
20
18
  <?php
21
19
 
22
- header('Content-Type: text/plain; charset=UTF-8');
23
-
24
20
  $str = 'ライスパスタライスカレーライスカレードリア';
25
21
 
26
22
  print_r([
@@ -52,7 +48,7 @@
52
48
  ]);
53
49
  ```
54
50
 
55
- `strtr` `preg_replace (単一の正規表現で処理)` においては一度置換したところを次回の置換対象から外してくれますが, `str_replace` `preg_replace (複数の正規表現で処理)` においては全く考慮してくれません. 速度面においても,僅かな違いですが,一般的には速い順に
51
+ **`strtr` `preg_replace (単一の正規表現で処理)` においては一度置換したところを次回の置換対象から外してくれますが, `str_replace` `preg_replace (複数の正規表現で処理)` においては全く考慮してくれません. **速度面においても,僅かな違いですが,一般的には速い順に
56
52
 
57
53
  1. `str_replace`
58
54
  2. `strtr` (実はもう1つ使い方があるがこの例のように連想配列で置換する場合)
@@ -61,13 +57,11 @@
61
57
 
62
58
  として差がつくと思うので,書きやすさも考慮して適宜使い分けてください.
63
59
 
64
- また正規表現の高度なテクニックですが,バックトラッキングコントロールを使うとまさに「あるバイト列以外のバイト列を直接マッチさせることもできます.
60
+ また正規表現の高度なテクニックですが,バックトラッキングコントロールを使うとまさに**「あるバイト列以外のバイト列」**を直接マッチさせることもできます.
65
61
 
66
62
  ```php
67
63
  <?php
68
64
 
69
- header('Content-Type: text/plain; charset=UTF-8');
70
-
71
65
  $str = 'ライスパスタライスカレーライスカレードリア';
72
66
 
73
67
  echo preg_replace(

3

a

2016/03/29 16:20

投稿

mpyw
mpyw

スコア5223

answer CHANGED
@@ -1,6 +1,6 @@
1
1
  まず前提として,この回答においては文字列ではなく**バイト列**という表記にします.日本語を相手にしても本当に1文字という単位で見てくれるのは`u`修飾子をつけた`preg_*`系の関数,あるいは文字コードをUTF-8として正しく指定した`mb_*`系の関数のみです.残りの関数は全てバイト単位で計算します.
2
2
 
3
- -[マルチバイト文字を扱う際に気をつけること](http://qiita.com/mpyw/items/a8dba1b80fe68523b8eb)
3
+ - [マルチバイト文字を扱う際に気をつけること](http://qiita.com/mpyw/items/a8dba1b80fe68523b8eb)
4
4
 
5
5
  本題に入ります.既に回答にありますが,**除外したいバイト列を空白に置換して残ったバイト列を得る**というアプローチにて`preg_replace`あるいは`preg_replace_callback`を使って済むのであればそれが一番簡単です.正規表現無しでも簡単に書ける範囲であれば`str_replace`や`strtr`を使うほうがよいでしょう.なお文字コードがUTF-8である場合は,正規表現の文字クラス`[]`を使わない限り,「文字列=バイト列」のように扱っても正しく動作します.このことは上にリンクしたQiitaの記事でも解説しています.
6
6
 

2

一応s修飾子を追加

2016/03/29 16:17

投稿

mpyw
mpyw

スコア5223

answer CHANGED
@@ -1,38 +1,68 @@
1
- 既に回答にありますが,`preg_replace`あるは`preg_replace_callback`を使って文字列置換済むのであればそれが一番簡単です.正規表現無簡単書ける範囲`str_replace``strtr`を使うほうがよいでしょう.但しこれらには微妙な違いがあるので注意してくださ.以下実行してみるとわかります.
1
+ まず前提として,この回答にいて文字列ではなく**バイト列**という表記にします.日本語を相手に本当1文字という単位見てくるのは`u`修飾子をつけた`preg_*`系の関数,あるいは文字コードUTF-8として正しく指定した`mb_*`系の関数のです.残の関数は全てバイト単位で計算します.
2
2
 
3
+ -[マルチバイト文字を扱う際に気をつけること](http://qiita.com/mpyw/items/a8dba1b80fe68523b8eb)
4
+
5
+ 本題に入ります.既に回答にありますが,**除外したいバイト列を空白に置換して残ったバイト列を得る**というアプローチにて`preg_replace`あるいは`preg_replace_callback`を使って済むのであればそれが一番簡単です.正規表現無しでも簡単に書ける範囲であれば`str_replace`や`strtr`を使うほうがよいでしょう.なお文字コードがUTF-8である場合は,正規表現の文字クラス`[]`を使わない限り,「文字列=バイト列」のように扱っても正しく動作します.このことは上にリンクしたQiitaの記事でも解説しています.
6
+
3
7
  ```php
4
8
  <?php
5
9
 
6
10
  header('Content-Type: text/plain; charset=UTF-8');
7
11
 
12
+ $str = 'ライスパスタカレーパスタドリア';
13
+
14
+ echo str_replace('パスタ', '', $str), "\n"; // ライスカレードリア
15
+ ```
16
+
17
+ 但しこれらには,複数の置換を同時に行う際に微妙な違いがあるので注意してください.以下を実行してみるとわかります.
18
+
19
+ ```php
20
+ <?php
21
+
22
+ header('Content-Type: text/plain; charset=UTF-8');
23
+
8
24
  $str = 'ライスパスタライスカレーライスカレードリア';
9
25
 
10
26
  print_r([
27
+
11
28
  'str_replace' => str_replace(
12
29
  ['カレーライス', 'カレー', 'ライス'],
13
30
  ['【カレーライス】', '【カレー】', '【ライス】'],
14
31
  $str
15
- ),
32
+ ), // 【ライス】パスタ【ライス】【【カレー】【ライス】】【カレー】ドリア
33
+
16
34
  'strtr' => strtr($str, [
17
35
  'カレーライス' => '【カレーライス】',
18
36
  'カレー' => '【カレー】',
19
37
  'ライス' => '【ライス】',
20
- ]),
38
+ ]), // 【ライス】パスタ【ライス】【カレーライス】【カレー】ドリア
39
+
21
40
  'preg_replace (複数の正規表現で処理)' => preg_replace(
22
41
  ['/カレーライス/', '/カレー/', '/ライス/'],
23
42
  '【$0】',
24
43
  $str
25
- ),
44
+ ), // 【ライス】パスタ【ライス】【【カレー】【ライス】】【カレー】ドリア
45
+
26
46
  'preg_replace (単一の正規表現で処理)' => preg_replace(
27
47
  '/カレーライス|カレー|ライス/',
28
48
  '【$0】',
29
49
  $str
30
- ),
50
+ ), // 【ライス】パスタ【ライス】【カレーライス】【カレー】ドリア
51
+
31
52
  ]);
32
53
  ```
33
54
 
34
- 正規表現の高度なテクニックすが,バックトラッキングコントロールを使うとまさ『「abc」言う塊以外の文字列』を直接マッチさることもできま
55
+ `strtr` `preg_replace (単一の正規表現で処理)` おいては一度置換したころを次回の置換対象からしてくれますが, `str_replace` `preg_replace (複数正規表現で処理)` においては全く考慮してくれまん. 速度面において,僅かな違いですが,一般的には速い順に
35
56
 
57
+ 1. `str_replace`
58
+ 2. `strtr` (実はもう1つ使い方があるがこの例のように連想配列で置換する場合)
59
+ 3. `preg_replace (単一の正規表現で処理)`
60
+ 4. `preg_replace (複数の正規表現で処理)`
61
+
62
+ として差がつくと思うので,書きやすさも考慮して適宜使い分けてください.
63
+
64
+ また正規表現の高度なテクニックですが,バックトラッキングコントロールを使うとまさに「あるバイト列以外のバイト列を直接マッチさせることもできます.
65
+
36
66
  ```php
37
67
  <?php
38
68
 
@@ -40,11 +70,17 @@
40
70
 
41
71
  $str = 'ライスパスタライスカレーライスカレードリア';
42
72
 
43
- print_r([
73
+ echo preg_replace(
44
- 'preg_replace (バックトラッキングコントロール)' => preg_replace(
45
- '/(?:カレー|ライス)(*SKIP)(*FAIL)|.+?(?=カレー|ライス|\z)/',
74
+ '/(?:カレー|ライス)(*SKIP)(*FAIL)|.+?(?=カレー|ライス|\z)/s',
46
- '【$0】',
75
+ '【$0】',
47
- $str
76
+ $str
48
- ),
77
+ ), "\n"; // ライス【パスタ】ライスカレーライスカレー【ドリア】
49
- ]);
50
- ```
78
+ ```
79
+
80
+ 上記の例では
81
+
82
+ 1. まず現在位置から「カレー」「ライス」いずれかにマッチするバイト列を探す.**マッチしたら何も無かったことにして3に進む.**マッチしなければ2に進む.
83
+ 2. **後ろに「カレー」「ライス」「末尾」のいずれかが来るように**,1バイト以上の可能な限り短いバイト列を探す.マッチしたら置換処理を行う.マッチしなければ3に進む.
84
+ 3. 現在位置を今マッチさせた文字列のぶんだけ進める.
85
+
86
+ という処理を行っています.

1

修正

2016/03/29 16:16

投稿

mpyw
mpyw

スコア5223

answer CHANGED
@@ -20,7 +20,7 @@
20
20
  ]),
21
21
  'preg_replace (複数の正規表現で処理)' => preg_replace(
22
22
  ['/カレーライス/', '/カレー/', '/ライス/'],
23
- ['【カレーライス】', '【カレー】', '【ライス】'],
23
+ '【$0】',
24
24
  $str
25
25
  ),
26
26
  'preg_replace (単一の正規表現で処理)' => preg_replace(