用正则表达式匹配字符串中间的可选子串

0 投票
2 回答
2617 浏览
提问于 2025-04-17 22:09

我正在尝试创建一个正则表达式,用来提取标题、副标题和出版社。我想知道怎么让副标题的搜索变成可选的。

我的格式是:

Title-(Subtitle)-[Publisher]

其中:

  • 标题 – 是我想在第一个捕获组中提取的字符串。
  • (副标题)– 是一个可选的字符串,用括号括起来,我想在第二个捕获组中提取。
  • [出版社] – 是一个用方括号括起来的字符串,我想在第三个捕获组中提取。

举个例子:

Programming.in.Python.3-(A.Complete.Introduction.to.the.Python.Language)-[Addison-Wesley]
Learning.Python-[O'Reilly]
Flask.Web.Development-(Developing.Web.Applications.with.Python)-[O'Reilly]

现在,我有一个正则表达式(在线查看),可以提取第一个和第三个部分:

(.*)-\((.*)\)-\[(.*)\]

我的问题是,我不知道怎么构建一个正则表达式,能够匹配第二行(标题在第一个组,第二个组应该是空的,第三个组是出版社),如果没有用括号括起来的副标题。这能在一个正则表达式中完成吗?

2 个回答

0

贪婪匹配是个好东西,因为它能让正则表达式的执行更高效。

为了享受这种性能上的好处,同时保持模式的逻辑,可以使用否定字符类,这种字符类里包含了接下来预期的分隔符字符。

([^-]*)-(?:\(([^)]*)\)-)?\[([^]]*)]

详细解析:Python 正则表达式示例

(          #start capture group 1
  [^-]*    #match zero or more non-hyphen characters
)          #end capture group 1
-          #match literal hyphen
(?:        #start non-capturing group
  \(       #match literal opening parenthesis
  (        #start capture group 2
    [^)]*  #match zero or more non-closing-parentheses
  )        #end capture group 2
  \)       #match literal closing parenthesis
  -        #match literal hyphen
)          #end non-capturing group
?          #make non-capturing group optional (zero or one occurrence)
\[         #match literal opening brace
(          #start capture group 3
  [^]]*    #match zero or more non-closing brace characters (no escaping needed)
)          #close capture group 3
]          #match literal closing brace (no escaping needed)
4

只需让第二个捕获变成可选的,使用 ? 就可以了。

(.*?)-(?:\((.*?)\)-)?\[(.*?)\]
       ^^^         ^^

另外,我把 .* 替换成了 .*?,这样可以避免贪婪匹配。

撰写回答