使用正则表达式,我想从Emacs组织模式文件中提取某些部分,这些文件是简单的文本文件。这些组织文件中的条目以*
开头,有时这些条目具有属性。一个简短的例子可以在下面找到:
import re
orgfiletest = """
* headline 0
* headline 1
:PROPERTIES:
:KEY: lala
:END:
* headline 2
* headline 3
:PROPERTIES:
:KEY: lblb
:END:
"""
我想提取所有具有属性的条目;提取的条目应包括这些属性。所以,我想收到以下文字:
* headline 1
:PROPERTIES:
:KEY: lala
:END:
和
* headline 3
:PROPERTIES:
:KEY: lblb
:END:
我从这样的事情开始
re.findall(r"\*.*\s:END:", orgfiletest, re.DOTALL)
但这也包括headline 0
和headline 2
,它们没有任何属性。我的下一次尝试是利用环顾四周,但无济于事。任何帮助深表感谢!
适用于我的更新/解决方案:
感谢所有帮助我找到解决方案的人!为了将来的参考,我包括了一个更新的MWE和适用于我的正则表达式:
import re
orgfiletest = """
* headline 0
more text
* headline 1
:PROPERTIES:
:KEY: lala
:END:
* headline foo 2
** bar 3
:PROPERTIES:
:KEY: lblb
:FOOBAR: lblb
:END:
* new headline
more text
"""
re.findall(r"^\*+ .+[\r\n](?:(?!\*)\s*:.+[\r\n]?)+", orgfiletest, re.MULTILINE)
答案 0 :(得分:2)
有一些可能性,包括非正则表达式解决方案 正如你特别要求的那样:
^\*\ headline\ \d+[\r\n] # look for "* headline digit(s) and newline
(?:(?!\*).+[\r\n]?)+ # followed by NOT a newline at the beginning
# ... anything else including newlines afterwards
# ... at least once
请参阅a demo on regex101.com(并注意修饰符x
和m
!)
Python
中,这将是:
import re
rx = re.compile(r'''
^\*\ headline\ \d+[\r\n]
(?:(?!\*).+[\r\n]?)+
''', re.VERBOSE | re.MULTILINE)
print(rx.findall(orgfiletest))
<小时/> 非正则表达式方式可能是(使用
itertools
):
from itertools import groupby
result = {}; key = None
for k, v in groupby(
orgfiletest.split("\n"),
lambda line: line.startswith('* headline')):
if k:
item = list(v)
key = item[len(item)-1]
elif key is not None:
result[key] = list(v)
print(result)
# {'* headline 1': [' :PROPERTIES:', ' :KEY: lala', ' :END:'], '* headline 3': [' :PROPERTIES:', ' :KEY: lblb', ' :END:', '']}
这有一个缺点,即从例如也会使用* headline abc
或* headliner***
。说实话,我在这里寻求regex
解决方案。
答案 1 :(得分:1)
我想你可以这样做。仅匹配包含 PROPERTIES
的rec (?ms)^\*(?:(?!^\*).)*?PROPERTIES(?:(?!^\*).)*
https://regex101.com/r/oZcos0/1
解释
(?ms) # Inline modifiers: Multi-line, Dot-all
^ \* # Start record: BOL plus *
(?: # Minimal matching
(?! ^ \* ) # Not a new record
.
)*?
PROPERTIES # Up to prop
(?: # Max matching up to begin new record
(?! ^ \* ) # Not a new record
.
)*
答案 2 :(得分:1)
尝试制作可读的正则表达式:
^\*\sheadline(?:(?!^\*\sheadline).)*:END:$
^\*\sheadline
- &gt;众所周知这个项目是这样开始的。
(?:(?!^\*\sheadline).)*
- &gt;只要它不包括我们如何知道新项目的开始就匹配任何内容。
:END:$
- &gt;它包括一行末尾的已知结束语句。