正規表現最短マッチ
正規表現を覚えたてのときぶち当たる壁があります。取得したい場所を指定してしているのに要らないところまで取得してしまう。例ではhtmlのclass名のみ取得したいときぶち当たります。
<div class="test"><div class="test__in">test</div></div>
class「test」のみ取得したいとき
/class=\"(.*)\"/
PHPでは
<?php $source = '<div class="test"><div class="test__in">test</div></div>'; $pattern = '/class=\"(.*)\"/'; preg_match($pattern,$source, $m); ?>
こんな感じで書いたとします。しかし結果は
になってしまいます。よく考えると確かにそうなります。
しかし解決方法がなかなか見当たらないのです。ググりたいけどどういう状況かを説明できないので、はじめの場合は苦戦します。実はこの状況「最短マッチ」といいます。私は「正規表現 手前のみ取得」でたどり着きました。
.*?
「最短マッチ」させるためには一般的には以下のように書きます。
/class=\"(.*?)\"/
PHPでは
<?php $source = '<div class="test"><div class="test__in">test</div></div>'; $pattern = '/class=\"(.*?)\"/'; preg_match($pattern,$source, $m); ?>
?(はてな)を加えるだけでなぜか取得できます。
なぜ.*?で取得できるのか
*(アスタリスク)や?(はてな)は量指定子文字といい、前の文字を何回でてくるか指定することができる文字です。
量指定子 | 説明 |
---|---|
* | 0回以上の繰り返しにマッチ |
? | 0回または1回の出現にマッチする表現 |
+ | 1回以上の繰り返しにマッチ |
{n} | n回の繰り返しにマッチする表現 |
{n,} | n回以上の繰り返しにマッチする表現 |
{n,m} | n回以上m回以下の繰り返しにマッチする表現 |
量指定子はデフォルトで「できるだけ長い文字列にマッチさせる特性(最長一致)」をもっています。そのため「*(アスタリスク)」はできる長く取得するため初めに書いたように予定していないところまで取得したのです。この特性を変更させるのが「?(はてな)」です。量指定子の後ろに「?」をつけると特性が「できるだけ短い文字列にマッチする特性(最短一致)」に変わります。上記の量指定子だけ覚えていると意味がわかりませんが、「?」には特性を変更できる特殊な能力があると覚えておくと便利に利用できます。
.* 最長一致
↓
.*? 最短一致
連続して取得したいとき
以下のソースのクラスを全て取得したいときはどのようにすればいいでしょうか。
<div class="test"><div class="test__in">test</div></div>
「test」「test__in」も取得したい。
PHPの場合では連続マッチできる関数があります。
preg_match 単一
↓
preg_match_all 連続
<?php $source = '<div class="test"><div class="test__in">test</div></div>'; $pattern = '/class=\"(.*?)\"/'; preg_match_all($pattern,$source, $matches, PREG_OFFSET_CAPTURE); foreach($matches[1] as $result){ echo str_replace(" ","<br>",$result[0]) . "<br>"; } ?>
「クラウドテック」です。 掲載案件では平均月60万、週3~4日勤務の案件が豊富で生活スタイルに合わせた働き方を設計できます。 また福利厚生が充実し旅行、レジャー、家事代行、ヘビーシッター、健康診断など100種類以上を無料で使えます。
- 97%がリモートのお仕事
- 週4日、週3日OKのお仕事多数
- 登録社数74万件業界トップクラス
- 2〜4週間程度でお仕事決定