プログラミングPHP 弟4章 4.8 正規表現


# PHPの正規表現モジュール

| 正規表現の種類 | POSIX | mbstring | Perl互換 |
|:-----:|:-----:|:-------:|:-------:|
| 正規表現の構文 | POSIX | Rubyなど | Perl |
| 拡張モジュール| regex | mbstring | PCRE |
| 関数名の接頭語 | ereg_ | mb_ | preg_ |
| 備考 | PHP5.3.0で非推奨 | 鬼車ライブラリ | PCREライブラリ |

# 正規表現の基本
/pattern/

# 正規表現パターン「.」
.は任意の1文字だが、改行を含む、含まないの扱いが以下で異なる。

## mbstringの正規表現パターン「.」
/m オプションあり（デフォルト)：改行を含む任意の1文字
/m オプションなし: 改行を除く任意の1文字

## Perl互換の正規表現パターン「.」
/s オプションあり: 改行を含む任意の1文字
/s オプションなし(デフォルト) : 改行を除く任意の1文字

#文字クラス []
[]で囲む　[^pattern] は、文字クラスの否定
ex) 

```php:
preg_match("/c[aeiou]t/","I cut my hand") //1を返す
preg_match("/c[^aeiou]t/","I cut my hand") //0を返す
```

# 選択肢 |
ex)

```php:
preg_match("/cat|dog/", "the cat") //1を返す
preg_match("/cat|dog/", "the dog") //1を返す
preg_match("/cat|dog/", "the rabbit") //0を返す
```

# 繰り返し ?, * , +, {
|量指定子| 意味 |
|:--:|:--:|
|? | 0 or 1回|
|* | 0回以上 |
|+ | 1回以上 |
|{n | n回 |
|{n, m} | n回以上m回以下 |
|{n,} | n回以上 |

★通常は、できるだけ長い範囲にマッチするようにするが、できるだけ短い範囲にマッチさせたい場合は、両指定子の後ろに?をつける
ex) 

|貪欲な量指定子| 貪欲でない量指定子 |　意味 |
|:--:|:--:|:--:|
|? |?? | 0 or 1回|
|* |*?| 0回以上 |
|+ | +? | 1回以上 |
|{n |{n? | n回 |
|{n, m} | {n, m}? |n回以上m回以下 |
|{n,} |{n,}? | n回以上 |

# 選択肢 |
ex)

```php:
preg_match("/^(cat|dog)$/", "cat") //1を返す
```

# デリミタ
/以外にも、英数字とバックスラッシュ以外の文字ならなんでもデリミタとして使える
ex)

```php:
preg_match("/\/usr\/local\//", "/usr/local/bin/perl"); //1を返す

preg_match("#/usr/local/#", "/usr/local/bin/perl"); //1を返す
```

# 文字クラス
|クラス| 説明 |
|:--:|:--:|
| [:alnum:]| 英数字 |
| [:alpha:] | アルファベット |
| [:ascii:] | 7ビットのASCII文字 |
| [:brank:] | スペース、タブ |
| [:cntrl:] | 制御文字 |
| [:digit:] | 数字|
| [:graph:] | 可視文字|
| [:upper:] | 英大文字|
| [:lower:] | 英小文字|
| [:print:]| 印字可能な文字 graph + 空白とタブ|
| [:punct:] | ピリオド、セミコロンなどの記号|
| [:space:] | 空白（改行、キャリッジリターン、タブ、スペース、垂直タブ|
|[:xdigit:] | 16進数字|
| \s | 空白文字|
|\S |空白文字以外|
|\w| ワード（識別子）文字|
|\W|ワード（識別子）文字以外|
|\d | 数字 |
|\D | 数字以外 |

# アンカー
|アンカー| マッチする対象 |
|:--:|:--:|
| ^ | 文字列の先頭、行頭 (/mフラグが有効な場合は、\nの直後) |
| $ | 文字列の末尾、行末 (/mフラグが有効な場合は、\nの直前)|
| [[:<:]]| 単語の先頭 |
| [[:>:]]| 単語の末尾 |
| \b | ワードの境界 |
| \B | ワードの境界以外 |
| \A | 文字列の先頭 |
| \Z | 文字列の末尾、あるいは最後の\nの直前 |
| \z | 文字列の末尾 |

# キャプチャしないグループ(?:subpattern)
(?:subpattern) とするとキャプチャしない
ex)

```php:
preg_match("/(?:ello)(.*)/", "jello biafra", $match);
```
→$match[1]はelloは入らず、biafraが入る。

# Perl互換正規表現　後置オプション(フラグ）
|修飾子| 意味 |
|:--:|:--:|
| /regexp/i | 大文字、小文字を区別しないマッチを行う |
| /regexp/s | ピリオド(.)を、改行(\n)も含めた任意の文字にマッチさせる |
| /regexp/x | パターンから空白文字やコメントを除去する |
| /regexp/m | 複数行モード。キャレット(^)は、改行(\n)の直後の文字、ドル記号($)は、改行(\n)の直前の文字にマッチさせる |
| /regexp/e | 置換文字にPHPのコードを指定すると、そのコードをeval()した結果で文字列を置き換える |
| /regexp/U|  サブパターンの貪欲さの指定を反転させる|
| /regexp/u | パターン文字列をUTF-8として扱う |
| /regexp/X | バックスラッシュの後に特別な意味を持たない文字が続いている場合にエラーを発生させる |
| /regexp/A | パターンの最初の文字が^であるかのように、先頭の文字にアンカーを設定する|
|/regexp/D | $を行末にのみマッチさせるようにする
| /regexp/S | パターンの構造をより慎重に解析し、ループ内などでの次回以降の実行速度を少し高速にする。 |

# mbstring　正規表現　後置オプション
|修飾子| 意味 |
|:--:|:--:|
| /regexp/m | ピリオド(.)を、改行(\n)も含めた任意の文字にマッチさせる |
| /regexp/s | 複数行モードでない。（mgstring正規表現は、デフォルトが複数行モード = Perl互換で/mオプションを指定している状態) |

# インラインオプション　(?flags:subpattern)または(?flags)
パターンの一部にだけ適用するオプション(フラグ)の指定
ex)

```php:
preg_match('/I like (?i:PHP)/' , 'I like pHp'); //1を返す
```

マイナス文字の後にオプション文字を指定すると、オプションを無効にできる
ex)
```php:
preg_match('/a(?i)b(?-i)c/' , 'aBc'); //1を返す
preg_match('/a(?i)b(?-i)c/' , 'aBC'); //0を返す
```

# 先読みと戻り読み
|書式| 意味 |
|:--:|:--:|
| (?=subpattern) | 肯定先読み |
| (?!subpattern) | 否定先読み |
| (?<=subpattern) | 肯定戻り読み |
| (?<!subpattern) | 否定戻り読み |

ex)
- foo(?=bar) 直後にbarがあるfoo(barは含まない)
- foo(?!bar)直後にbarがないfoo(barは含まない)
- (?<=bar)foo 直前に barがあるfoo(barは含まない)
- (?<!bar)foo 直前にbarがないfoo(barは含まない)

# 条件式
(?(条件)yespattern|nopattern)

# 関数 (mbstring)
## mb_regex_set_options([string $options])
mgstring正規表現の関数が使用するオプションや構文モードを取得または設定する。
$optionsに設定可能なオプション、構文モードは以下
### mb_regex_set_options()のオプション
|オプション文字| 意味 |
|:--:|:--:|
| i | 大文字小文字の区別なし |
|x | 拡張パターン形式を使用 (空白、#以降を無視)|
|m |「.」が改行にマッチ|
|s| ^は\A（文字列の先頭）, $は\Z（文字列の末尾)と同一 ,NOT複数行モード|
|p| mとsを両方指定と同一|
|l | 貪欲なマッチ（最も長くマッチするものを探す)|
|n| 空のマッチを無視|
|e|結果のコードをeval()する|

### mb_regex_set_options()の構文モード
|モード| 意味 |
|:--:|:--:|
| j | java |
| u | GNU regex|
| g | grep |
| c | Emacs |
| r | Ruby |
| z | Perl |
| b | POSIX Basix regex|
| d | POSIX Extended regex|

★デフォルトのオプションは「msr」

## mb_regex_encoding([string $encoding])
mbstring正規表現関数が使用する文字エンコーディングを取得または設定する

## mb_ereg_match(string $pattern, string $string [, string $option = "msr"])
マッチすればtrue,そうでない場合はfalseを返す

## mb_ereg(string $pattern, string $string [, array $regs])
$regsはマッチ結果。$regs[0]にはマッチした文字列全体、$regs[1]以降には、サブパターンにマッチした要素が入る。
戻り値はマッチすれば1、そうでなければ0を返す。

## mb_eregi
mb_ereg の、大文字小文字の区別を行わない関数

## mb_ereg_search_init(), mb_ereg_search(),mb_ereg_search_getregs()

- mb_ereg_search_init(string $string [,string $pattern[, string $option = "msr"]])
マッチング処理の初期化

- mb_ereg_search([string $pattern [,string $option = "ms"]])
マッチングの実行

- mb_ereg_search_getargs()
マッチング部分の取り出し
戻り値 = array 
最初の要素はパターンにマッチした文字列全体、
2番目以降の要素はサブパターンにマッチした部分

ex)

```php:
$pattern = '<h([0-9])>';
$subject = '<h1><h2><h3>';
mb_ereg_search_init($subject, $pattern);
while(mb_ereg_search()){
	$regs = mb_ereg_search_getregs();
	print_r($regs);
}
```

結果

```php:
Array
(
    [0] => <h1>
    [1] => 1
)
Array
(
    [0] => <h2>
    [1] => 2
)
Array
(
    [0] => <h3>
    [1] => 3
)
```

## mb_ereg_replace(string $pattern, string $replacement, string $string [, string $option = "msr" )
文字列をパターンで検索し、マッチした部分を置換文字列に置換した結果の文字列を変えず。マッチしない場合は元の文字列をそのまま返す。
第2引数に与える置換文字列では、パターン全体に一致した部分を\0,サブパターンに一致した部分を\1,\2…で参照することができる。
ex)

```php:
$pattern = '([0-9]+)/([0-9]+)/([0-9]+)';
$replacement = '\1年 \2月 \3日';
$string = '今日は2013/12/31です';
echo mb_ereg_replace($pattern, $replacement, $string);
```

結果：　今日は2013年 12月 31日です

## mb_eregi_replace()
mb_ereg_replaceとの違いは、大文字小文字の区別を行わない事のみ

## mb_split(string $pattern, string $string [,int $limit = -1])
文字列を、パターンで区切り、結果を配列で返す。$limitは最大の区切り個数

# 関数 (Perl互換)
## preg_match(string $pattern, string $string [,array $captured ])
stringにpatternがマッチする場合は1を、そうでない場合は0を返す。captured[0]にはマッチした文字列全体が、captured[1]にはサブパターンに一致した部分が入る。
★preg_matchi()関数は存在しないので、パターンの中でiフラグを使用する。

## preg_match_all(string $pattern, string $string, array $matches, [, order])
最後にマッチした場所以降でマッチを繰り返し、マッチが行えなくなるまで処理を続ける。
orderにはPREG_PATTERN_ORDER（デフォルト)か、PREG_SET_ORDERのいずれかを指定する。
ex)
- PREG_PATTERN_ORDER
$matches[0] はパターン全体にマッチした文字列の配列、 $matches[1] は第 1 のキャプチャ用サブパターンにマッチした文字列の配列、 といった順番となる。

```php:
preg_match_all("|<[^>]+>(.*)</[^>]+>|U",
    "<b>example: </b><div align=left>this is a test</div>",
    $out, PREG_PATTERN_ORDER);
echo $out[0][0] . ", " . $out[0][1] . "\n";
echo $out[1][0] . ", " . $out[1][1] . "\n";
```

結果：

```php:
<b>example: </b>, <div align=left>this is a test</div>
example: , this is a test
```

- PREG_SET_ORDER

$matches[0] は 1 回目のマッチングでキャプチャした値の配列、 $matches[1] は 2 回目のマッチングでキャプチャした値の配列、 といった順序となる。

```php:
preg_match_all("|<[^>]+>(.*)</[^>]+>|U",
    "<b>example: </b><div align=left>this is a test</div>",
    $out, PREG_SET_ORDER);
echo $out[0][0] . ", " . $out[0][1] . "\n";
echo $out[1][0] . ", " . $out[1][1] . "\n";
```

結果：

```php:
<b>example: </b>, example:
<div align="left">this is a test</div>, this is a test
```

## preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )
$subject が置換元。string または array。戻り値の型は$subjectの型と同一。 $limitは、置換する最大数。デフォルト= -1 (全て置換)

## array preg_split ( string $pattern , string $subject [, int $limit = -1 [, int $flags = 0 ]] ) 
分割して配列にする。

## array preg_grep ( string $pattern , array $input [, int $flags = 0 ] )
指定された配列の要素のうち、パターンにマッチするものだけを返す。

##　string preg_quote ( string $str [, string $delimiter = NULL ] )
正規表現構文の特殊文字の前にバックスラッシュを挿入します。 この関数は、実行時に生成される文字列をパターンとしてマッチングを行う必要があり、 その文字列には正規表現の特殊文字が含まれているかも知れない場合に有用です。