我正在尝试使子字符串可选。这是来源:
Movie TOTO S09 E22 2022 Copyright
Run Code Online (Sandbox Code Playgroud)
我想选择性地捕获子字符串:S09 E22
到目前为止我已经尝试过:
/(Movie)(.*)(S\d\d\s*E\d\d)?/gmi
Run Code Online (Sandbox Code Playgroud)
问题是它最终通过匹配S09 E22 2022 Copyright而不仅仅是S09 E22:
Match 1 : 0-33 Movie TOTO S09 E22 2022 Copyright
Group 1 : 0-5 Movie
Group 2: 5-33 TOTO S09 E22 2022 Copyright
Run Code Online (Sandbox Code Playgroud)
有办法解决这个问题吗?
问候
您得到该匹配是因为.*是贪婪的并且会首先匹配直到字符串末尾。
然后你(S\d\d\s*E\d\d)?是可选的,所以这将保持匹配并且不会回溯。
如果您不希望 S09 或 E22 部分匹配,并且年份的 4 位数字不是强制性的,并且您的电影长度超过 1 个单词,则可以使用 pcre:
\b(Movie)\b\h+((?:(?!\h+[SE]\d+\b).)*)(?:\h(S\d+\h+E\d+))?
Run Code Online (Sandbox Code Playgroud)
\b(Movie)\b捕捉这个词电影(捕获组
(?:非捕获组作为整体部分重复
(?!\h+[SE]\d+\b).如果 S01 或 E22 部分不直接位于右侧,则匹配任何字符(其中[SE]匹配 aS或Echar,并\h匹配水平空白字符))*关闭非捕获组并可选择重复它)关闭捕获组(?:\h(S\d+\h+E\d+))(可选)捕获 S01 E22 部分(\d+匹配 1 个或多个数字)S01 E22 部分的捕获组的另一个选项,或者匹配该行的 redt
\b(Movie)\h+([^S\n]*(?:S(?!\d+\h+E\d+\b)[^S\n]*)*+)(S\d+\h+E\d+)?
Run Code Online (Sandbox Code Playgroud)
根据您显示的示例和尝试,请尝试以下正则表达式。
^Movie\s+\S+\s+(S\d{2}\s+E\d{2}(?=\s+\d{4}))
Run Code Online (Sandbox Code Playgroud)
这是使用正则表达式的在线演示。
说明:为上面使用的正则表达式添加详细说明。
^Movie\s+\S+\s+ ##Matching string Movie from starting of value followed by spaces non-spaces and spaces.
(S\d{2}\s+E\d{2} ##Creating one and only capturing group where matching:
##S followed by 2 digits followed by spaces followed by E and 2 digits.
(?=\s+\d{4}) ##Making sure by positive lookahead that previous regex is followed by spaces and 4 digits.
) ##Closing capturing group here.
Run Code Online (Sandbox Code Playgroud)
如果其他部分不存在,则使点变得懒惰.*?并强制其匹配到$结束的想法。
Movie\s*(.*?)\s*(S\d\d\s*E\d\d|$)
Run Code Online (Sandbox Code Playgroud)
请参阅 regex101 上的演示(我还在\s*捕获周围添加了一些空格)