我正在尝试使用单行正则表达式解析导出为 taskpaper 格式的 Omnifocus 项目,但我很难捕获标签,特别是每个 @ 标签都有一个捕获组。
这是一个任务纸片断:
- My Project
- My Sub-Project @parallel(true) @autodone(false) @done(2017-04-01 11:12)
- Task A: Do (1, 2, 3, @) @parallel(true) @autodone(false) @done(2017-04-01 10:43)
- Task B: Do (4, 5, 6, @) @parallel(true) @autodone(false) @flagged @done(2017-04-01 10:58)
- Task C: Read https://stackoverflow.com/ @parallel(true) @autodone(false) @flagged @done(2017-04-01 10:41)
以及我使用的 Python 正则表达式:
^(\t*)-(.*?)((@\w+\((.*)\))*)$
请您参考如下方法:
您可以将字符串的整个部分与 @-group 匹配,然后拆分或匹配您需要处理的那些部分与另一个嵌套的 re.findall:
import re
rx = re.compile(r"^(\t*)-\s*(.*?)((?:\s+@\w+(?:\([^)]*\))?)*)$")
ss = ["- My Project", " - My Sub-Project @parallel(true) @autodone(false) @done(2017-04-01 11:12)", " - Task A: Do (1, 2, 3, @) @parallel(true) @autodone(false) @done(2017-04-01 10:43)", " - Task B: Do (4, 5, 6, @) @parallel(true) @autodone(false) @flagged @done(2017-04-01 10:58)", " - Task C: Read https://stackoverflow.com/ @parallel(true) @autodone(false) @flagged @done(2017-04-01 10:41)"]
for s in ss:
match = [(m.group(2), re.findall(r'(@\w+)\(([^)]*)\)', m.group(3))) for m in rx.finditer(s)]
print(match)
结果:
[('My Project', [])]
[('My Sub-Project', [('@parallel', 'true'), ('@autodone', 'false'), ('@done', '2017-04-01 11:12')])]
[('Task A: Do (1, 2, 3, @)', [('@parallel', 'true'), ('@autodone', 'false'), ('@done', '2017-04-01 10:43')])]
[('Task B: Do (4, 5, 6, @)', [('@parallel', 'true'), ('@autodone', 'false'), ('@done', '2017-04-01 10:58')])]
[('Task C: Read https://stackoverflow.com/', [('@parallel', 'true'), ('@autodone', 'false'), ('@done', '2017-04-01 10:41')])]
查看 Python demo
主要图案细节:
^- 字符串的开始(\t*)- 第 1 组:零个或多个标签-\s*- 一个连字符和 0+ 个空格(.*?)- 第 2 组:除换行符以外的任何 0+ 个字符((?:\s+@\w+(?:\([^)]*\))?)*)- 第 3 组捕获 0+ 个序列\s+- 1+ 个空格@\w+-@后跟 1+ 个单词字符(?:\([^)]*\))?- 一个可选的序列\(- 一个([^)]*-) 以外的 0+ 个字符\)- 一个)
$- 字符串结尾。
