オプションは、2つのアンダースコアを一致させることです。
__
次に、現在の位置の前に2つのアンダースコアがないかどうかを確認するために、否定的な見方をします。
__(?!__)
そうでない場合は、任意の文字に一致します。
__(?!__).
前の1回以上繰り返します。
__((?!__).)+
最後に、別の2つのアンダースコアを一致させます。
__((?!__).)+__
これが最終的な解決策です。
ちょっとしたデモ:
<?php
$text = '__This_is__ a __test__';
preg_match_all('/__(?:(?!__).)+__/', $text, $matches);
print_r($matches);
?>
生成:
Array
(
[0] => Array
(
[0] => __This_is__
[1] => __test__
)
)
イデオネに見られるように。
編集
デモで非キャプチャグループを使用したことに注意してください。そうしないと、出力は次のようになります。
Array
(
[0] => Array
(
[0] => __This_is__
[1] => __test__
)
[1] => Array
(
[0] => s
[1] => t
)
)
つまり、一致した最後の文字((?!__).)はグループ1でキャプチャされます。
グループの詳細については、http://www.regular-expressions.info/brackets.htmlを参照してください。