【问题标题】:match regular expression without capture匹配正则表达式而不捕获
【发布时间】:2015-08-05 18:04:46
【问题描述】:

我想用正则表达式提取一些模式。作为简化示例,我有下面的文本片段,我想提取第二个字段不带下划线的文本:

  1. main_opt.otherstuff 应该返回三个字段:"main""opt""otherstuff"
  2. main.otherstuff 应该返回三个字段:"main""""otherstuff"

如果我将正则表达式指定为^([^_]+)_?([^.]+)?\\.(.+)$,我可以得到这个。但是,我想知道我是否可以更改这种模式 _?([^.]+)?,因为它们是同一个子模式的一部分,所以只指定了一个 ?

我尝试过([^_]+)((?=_)[^.]+)?\\.(.+)$([^_]+)((?:_)[^.]+)?\\.(.+)$,但它们在第二个字段中返回“_opt”而不是“opt”。 (如果这很重要,我正在使用 python 的 re 包。)

【问题讨论】:

  • "main", "", "otherstuff" 是想要的结果还是您只是报告结果?
  • @dawg:是的,这三个字段是我想要的结果。

标签: python regex


【解决方案1】:

您可以将它们分组到非捕获组(?: ... ),但它不会比您原来的解决方案更漂亮:

^([^_]+)(?:_([^.]+))?\\.(.+)$

Demo

在 Python 控制台上测试:

>>> re.findall(r'^([^_]+)(?:_([^.]+))?\.(.+)$', "main_opt.otherstuff")
[('main', 'opt', 'otherstuff')]
>>> re.findall(r'^([^_]+)(?:_([^.]+))?\.(.+)$', "main.otherstuff")
[('main', '', 'otherstuff')]

【讨论】:

  • regex101 行为并不总是与实际行为相同。您应该使用 python 控制台进行测试。
  • 我仍然得到相同的结果...在控制台上添加了结果以确保完整性,感谢您的反馈
  • 我相信(?:s)?他不想要一个空的第二个捕获组,但也许我还不太了解要求。
  • 我引用他的话:"main.otherstuff 应该返回三个字段:"main"、""、"otherstuff""
  • 好的,在这种情况下,您应该排除第一个字符类中的点以使模式更高效(回溯更少)
【解决方案2】:

拆分可能会简化方法:

>>> re.split(r'_|\.', 'main_opt.otherstuff')
['main', 'opt', 'otherstuff']
>>> re.split(r'_|\.', 'main.otherstuff')
['main', 'otherstuff']

【讨论】:

  • 为什么不呢,但这并不能保证组的数量(少于 4 个,多于 1 个)。
  • 我要求 OP 澄清他是否在所有情况下都需要 3 个组。也许我是个傻瓜,但这篇文章对我来说并不清楚。
  • 喜欢这里的很多帖子。
【解决方案3】:

我认为您可以更简单地做到这一点,而无需使用正则表达式,只需拆分两次。

mainopt, _, otherstuff = wholething.partition('.')
main, _, opt = mainopt.partition('_')

这是对不同输入的作用:

`"main_opt.otherstuff"` -> `"main"`, `"opt"`, `"otherstuff"`
`"main.otherstuff"` -> `"main"`, `""`, `"otherstuff"`
`"main_opt"` -> `"main"`, `"opt"`, `""`

如果您想要不同的优先级,您可以更改顺序,或者如果您想要不同的关联性(例如,如果最后一个示例应该给出 ""、@987654326 @, "main_opt")。

【讨论】:

    猜你喜欢
    • 2021-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-30
    • 2016-04-06
    • 1970-01-01
    相关资源
    最近更新 更多