RegEx:从右到左匹配第一个数字不在任何类型的括号中

时间:2013-06-01 17:24:49

标签: regex regex-negation

我正在搜索单个正则表达式,以匹配从右侧开始的字符串中的任何类型括号中的第一个数字。这可能吗?

示例文字:

[X-Y] Prelude of 2013 - 06 - From the darkness [FLAC 1080p][E0ECC01D].mkv
c:\Files\Prelude 2013[X-Y] Prelude of 2013 - 12 - 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

各行的预期结果

06
12
09

2 个答案:

答案 0 :(得分:2)

您可以使用这种模式:

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中的数字(?<n>\d++)

答案 1 :(得分:0)

描述

提供所有方括号内的文字是单一嵌套的,并且是开放的&amp; amp;关闭括号匹配,然后你可以简单地取你的输入字符串并删除所有括号内的文本,然后应用一个简单的正则表达式来解析最后一个数字值。

要删除您可以使用的方括号内的文字:\[[^\]]*?\]|\([^)]*?\)|\{[^}]*?\}|\<[^>]*?\>

enter image description here

要解析剩余字符串中的最后一位数字:.*\D(\d+)。这将查找由非数字字符进行的最后一组数字。如果匹配成功,则组1将具有匹配中的所有数字。

enter image description here

实施例

你没有列出一种语言,所以我只是在这里使用powershell来表示逻辑,以及它们如何协同工作。

$string = 'c:\Programm Files\Yamato 2198[M-L]Space Battleship Yamato 2199 - 09 - Mechanischer Gefangener [FLAC 1080p BD][19066E4A].mkv'
write-host "Input String: '$string'"
$string = $String -replace '\[[^\]]*?\]|\([^)]*?\)|\{[^}]*?\}|\<[^>]*?\>', ""
write-host "No Brackets: '$string'"
if ($string -match '.*\D(\d+)') {
    Write-Host "found the following matches"
    $Matches
    } else {
    Write-Host "no matches found"
    } # end if

产量

Input String: 'c:\Programm Files\Yamato 2198[M-L]Space Battleship Yamato 2199 - 09 - Mechanischer Gefangener [FLAC 1080p BD][19066E4A].mkv'
No Brackets: 'c:\Programm Files\Yamato 2198Space Battleship Yamato 2199 - 09 - Mechanischer Gefangener .mkv'
found the following matches

Name                           Value                                                                                                                      
----                           -----                                                                                                                      
1                              09                                                                                                                         
0                              c:\Programm Files\Yamato 2198Space Battleship Yamato 2199 - 09