0

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

示例文本:

[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
4

2 回答 2

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>\d++)在命名的捕获组 n

于 2013-06-01T17:36:13.563 回答
0

描述

如果所有括号内的文本都是单嵌套的并且左右括号匹配,那么您可以简单地获取输入字符串并首先删除所有括号内的文本,然后应用一个简单的正则表达式来解析最后一个数字值。

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

在此处输入图像描述

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

在此处输入图像描述

例子

你没有列出一种语言,所以我只是在这里使用 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                                                             
于 2013-06-02T01:19:32.317 回答