回答編集履歴
9
a
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
|
-
|
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
あ
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
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
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
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
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
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修飾子を追加
answer
CHANGED
@@ -1,38 +1,68 @@
|
|
1
|
-
|
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
|
-
正規表現
|
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
|
-
|
73
|
+
echo preg_replace(
|
44
|
-
'preg_replace (バックトラッキングコントロール)' => preg_replace(
|
45
|
-
|
74
|
+
'/(?:カレー|ライス)(*SKIP)(*FAIL)|.+?(?=カレー|ライス|\z)/s',
|
46
|
-
|
75
|
+
'【$0】',
|
47
|
-
|
76
|
+
$str
|
48
|
-
|
77
|
+
), "\n"; // ライス【パスタ】ライスカレーライスカレー【ドリア】
|
49
|
-
]);
|
50
|
-
```
|
78
|
+
```
|
79
|
+
|
80
|
+
上記の例では
|
81
|
+
|
82
|
+
1. まず現在位置から「カレー」「ライス」いずれかにマッチするバイト列を探す.**マッチしたら何も無かったことにして3に進む.**マッチしなければ2に進む.
|
83
|
+
2. **後ろに「カレー」「ライス」「末尾」のいずれかが来るように**,1バイト以上の可能な限り短いバイト列を探す.マッチしたら置換処理を行う.マッチしなければ3に進む.
|
84
|
+
3. 現在位置を今マッチさせた文字列のぶんだけ進める.
|
85
|
+
|
86
|
+
という処理を行っています.
|
1
修正
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(
|