我有一个正则表达式来匹配字符串的各个部分(特别是带有修饰的肽序列),并且我想使用re.findall来获取字符串的所有部分:

该序列可以以可选的后缀开头,该后缀可以是任何非大写字母字符串,后跟-.

该序列还可以具有以-开头的前缀,后跟非大写字母字符串.

序列的其余部分应该用大写字母分隔,每个字母都有一个可选的前缀.

例如.

"foo-ABcmCD-bar"->['foo-','A','B','cmC','D','-bar']

"DEF"->['','D','E','F','']

"WHATEVER-foo"->['', 'W', 'H', 'A', 'T', 'E', 'V', 'E', 'R', '-foo']

"cmC-foo"->['', 'cmC', '-foo']

"ac-cmC-foo"->['ac-', 'cmC', '-foo']

我所拥有的是:

(?:(^(?:[^A-Z]+-)?)|((?:-[^A-Z]+)?$)|((?:[^A-Z]*)?[A-Z]))

捕获组1 (^(?:[^A-Z]+-)?)应该捕获可选的前缀或空字符串. 捕获组2 ((?:-[^A-Z]+)?$)应该捕获可选后缀或空字符串. 捕获组3((?:[^A-Z]*)?[A-Z])被认为捕获字符串的其余部分中可能具有非大写字符的子串的任何大写字符.

我得到可选的前缀或空字符串.

后缀似乎几乎可以工作--但如果有后缀,则行尾匹配两次,一次与后缀匹配,另一次与空字符串匹配.

>>> re.findall(r,"foo-ABC-bar")
['foo-', 'A', 'B', 'C', '-bar', '']
>>> re.findall(r,"ABC-bar")
['', 'A', 'B', 'C', '-bar', '']
>>> re.findall(r,"ABcmC")
['', 'A', 'B', 'cmC', '']

即,我如何处理多余的空字符串,或者为什么$匹配两次?

示例: https://regex101.com/r/koZPOD/1

推荐答案

这个问题已经有了三个答案,都是关于如何编写有效的正则表达式,但没有一个是关于如何修复您的正则表达式的.你的答案几乎是正确的:只需要做一点小小的修改.

[.]为什么$要匹配两次?

以下是相关部分:

(?:-[^A-Z]+)?$

如您所见,您匹配的是$,a zero-width assertion之前的一个可选模式.也就是说,在foo-A-bar匹配-bar后,引擎继续到它后面的位置,在那里它找不到-[^A-Z]+,但再次找到$.因为前者是可选的,所以这被记录为另一场比赛.

[.]如何删除多余的空字符串[?]

我们显式地告诉引擎匹配$ iff,它的前面要么是-[^A-Z]+(即有后缀),要么是不是[^A-Z](即没有后缀):

(?:
  (^(?:[^A-Z]+-)?)
|
  ((?:-[^A-Z]+|(?<![^A-Z]))$)
|
  ((?:[^A-Z]*)?[A-Z])
)

试试看on regex101.com个.

(regex101.com的Python风格不能反映实际结果,所以我改用了PCRE2.)

此外,最外面的(?:-)(?:[^A-Z]*)?中的(?:-)?也是不必要的;您可以完全删除它们.(?<![^A-Z])也可以简化为(?<=[A-Z]).

(^(?:[^A-Z]+-)?)
|
((?:-[^A-Z]+|(?<=[A-Z]))$)
|
([^A-Z]*[A-Z])

试试看on regex101.com个.

删除捕获组以使其对.findall()友好:

pattern = re.compile(r'^(?:[^A-Z]+-)?|(?:-[^A-Z]+|(?<=[A-Z]))$|[^A-Z]*[A-Z]')

for testcase in testcases:
  print(f'{testcase!r:<16}: {pattern.findall(testcase)}')
'foo-ABcmCD-bar': ['foo-', 'A', 'B', 'cmC', 'D', '-bar']
'DEF'           : ['', 'D', 'E', 'F', '']
'WHATEVER-foo'  : ['', 'W', 'H', 'A', 'T', 'E', 'V', 'E', 'R', '-foo']
'foo-ABC-bar'   : ['foo-', 'A', 'B', 'C', '-bar']
'ABC-bar'       : ['', 'A', 'B', 'C', '-bar']
'ABcmC'         : ['', 'A', 'B', 'cmC', '']
'foo-abCD'      : ['foo-', 'abC', 'D', '']
'abCD'          : ['', 'abC', 'D', '']

Python相关问答推荐

单击Cookie横幅错误并在Selenium中启用搜索栏

修剪Python框架中的尾随NaN值

如何在Pandas 中存储二进制数?

根据多列和一些条件创建新列

是否有方法将现有的X-Y图转换为X-Y-Y1图(以重新填充)?

Django文件上传不起作用:文件未出现在媒体目录或数据库中

如何才能将每个组比上一组增加N %?

Pandas read_jsonfuture 警告:解析字符串时,to_datetime与单位的行为已被反对

如何获取Django REST框架中序列化器内部的外卡属性?

Python主进程和分支进程如何共享gc信息?

如何使用上下文管理器创建类的实例?

Pandas 除以一列中出现的每个值

jit JAX函数中的迭代器

利用Selenium和Beautiful Soup实现Web抓取JavaScript表

部分视图的DataFrame

pandas在第1列的id,第2列的标题,第3列的值,第3列的值?

改进大型数据集的框架性能

从嵌套的yaml创建一个嵌套字符串,后面跟着点

什么是合并两个embrame的最佳方法,其中一个有日期范围,另一个有日期没有任何共享列?

搜索按钮不工作,Python tkinter