我正在尝试从EBML定义中提取所有匹配项,如下所示:
| + A track
| + Track number: 3
| + Track UID: 724222477
| + Track type: subtitles
...
| + Language: eng
...
| + A track
| + Track number: 4
| + Track UID: 745646561
| + Track type: subtitles
...
| + Language: jpn
...
我希望所有出现的“语言:???”当前面有“Track type:subtitles”。我尝试了几种变体:
Track type: subtitles.*Language: (\w\w\w)
我在Ruby中使用多行修饰符,因此它匹配换行符(如其他语言中的's'修饰符)。
这样可以获得最后次出现,在上例中,它将是'jpn',例如:
string.scan(/Track type: subtitles.*Language: (\w\w\w)/m)
=> [["jpn"]]
我想要的结果:
=> [["eng"], ["jpn"]]
完成此任务的正确正则表达是什么?
答案 0 :(得分:7)
你需要通过更改它来使你的正则表达式非贪婪:
.*
对此:
.*?
你的正则表达式从Track type: subtitles
的第一次出现到Language: (\w\w\w)
的最后一次出现是匹配的。使它非贪婪将起作用,因为它匹配尽可能少的字符。
答案 1 :(得分:3)
您需要使用延迟量词而不是.*
。试试这个:
/Track type: subtitles.*?Language: (\w\w\w)/m
这可以让您在每个“Language: ???
”之后第一次出现“Track type: subtitles:
”。但如果某个跟踪(类型subtitles
)缺少Language
字段,则会感到困惑。
另一种方法是:
/^\| \+ (?:(?!^\| \+).)*?\+ Track type: subtitles$(?:(?!^\| \+).)*?^\| \+ Language: (\w+)$/m
看起来有点凌乱,但应该照顾前一个问题。
更简洁的方法是对字符串进行标记:
/^\| \+ ([^\r\n]+)|^\| \+ Track type: (subtitles)|^\| \+ Language: (\w+)/m
(记下空格数)
对于每个匹配,您可以检查定义了哪个捕获组。任何一场比赛只有一组具有任何价值。
subtitles
。subtitles
时,请报告该曲目。