您可以使用这种模式:
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/>';
}
解释:
所有量词都是所有格,所有组都是原子的,除了捕获组以获得更好的性能。
这个想法是尽可能重复包含数字捕获组的模式(在第一个原子组中)。在每次出现时,旧的捕获结果都会被新的覆盖,直到模式失败。因此,您获得了最后一个数字。
在重复组中,您可以找到不同可能性之间的交替:
前三个对于不同类型的大括号是相同的,即 : []
, ()
,{}
并处理嵌套结构:
(\[(?>[^][]++|(?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
最后两个交替:
- 有助于联合其他交替:
[^][)(}{\d]++ # all characters that are not braces or digits one or more times
- 数字:(?<n>\d++)
在命名的捕获组 n