次のようなパターンを使用できます。
ruby (php でも動作します):
(?>(?<s>\[(?>[^\]\[]++|\g<s>)*+\])|(?<p>\((?>[^()]++|\g<p>)*+\))|(?<c>\{(?>[^{}]++|\g<c>)*+\})|[^\d\[\](){}]++|(?<n>\d++))++
php:
~(?>(\[(?>[^][]++|(?1))*+])|(\((?>[^)(]++|(?2))*+\))|(\{(?>[^}{]++|(?3))*+\})|[^][)(}{\d]++|(?<n>\d++))++~
。ネット:
(?>(\[(?>[^\]\[]+|(\k<1>))*\])|(\((?>[^)(]+|(\k<2>))*\))|(\{(?>[^}{]+|(\k<3>))*\})|[^\]\[)(}{\d]+|(?<n>\d+))+
これらのパターンは、ネストされたブラケットと壊れた構造を処理できます。PHP の例:
<?php
$subjects = array(
"[X-Y] Prelude of 2013 - 06 - From the darkness [FLAC 1080p][E0ECC01D].mkv",
"c:\Programm Files\Yamato 2199[M-L]Space Battleship Yamato 2199 - 09 - Mechanischer Gefangener [FLAC 1080p BD][19066E4A].mkv",
"c:\Programm Files\Yam{ato 2195[M-L]Space} Bat{tlesh}ip Yamato (2[19)(9] - (09 10)) - Mechanischer Gefangener [FLAC 1080p BD][19066E4A][.mkv",
"name 34 [more(]stuff).avi",
"name 34 [[more]stuff].mkv");
$pattern = '~(?>(\[(?>[^][]++|(?1))*+])|(\((?>[^)(]++|(?2))*+\))|(\{(?>[^}{]++|(?3))*+\})|[^][)(}{\d]++|(?<n>\d++))++~';
?><pre><?php
foreach ($subjects as $subject) {
preg_match($pattern, $subject, $match);
echo (isset($match['n'])) ? $match['n'] : 'no match';
echo '<br/>';
}
説明:
すべての量指定子は所有格であり、パフォーマンスを向上させるための捕捉グループを除いて、すべてのグループはアトミックです。
アイデアは、数字のキャプチャ グループを含むパターン (最初のアトミック グループ内) を可能な限り繰り返すことです。パターンが失敗するまで、発生するたびに古いキャプチャ結果が新しい結果で上書きされます。したがって、最後の番号を取得します。
繰り返されるグループ内では、さまざまな可能性の代替を見つけることができます。
最初の 3 つは、さまざまな種類の中括弧、つまり : []
、()
、{}
およびネストされた構造を扱う場合と同じです。
(\[(?>[^][]++|(?1))*+])
(\((?>[^)(]++|(?2))*+\))
(\{(?>[^}{]++|(?3))*+\})
角かっこの詳細:
( #begin capturing group 1
\[ # opening square bracket
(?> # begin atomic group
[^][]++ # all characters that are not square brackets one or more times
| # OR
(?1) # repeat the capturing group 1
)*+ # repeat the atomic group zero or more times
] # closing square bracket
) #end capturing group 1
最後の 2 つの交代:
-他のオルタネーションを結合するのに便利:
[^][)(}{\d]++ # all characters that are not braces or digits one or more times
-数字:(?<n>\d++)
名前付きキャプチャ グループ n 内