我有一个input text file看起来像这样(" ......"实际上并不在原文中,但我用它来忽略一些冗长且可能不相关的文字; ^ L& #34;表示每个页面的开头(注意:" ^ L"键入为控制字符,而不是字符" ^"和字符" L") ):
(Begin text)
.. A language ...
^LIntroduction
6
A preferable alternative is ...
1.2.1 Abstraction by Parameters
Abstraction allows us, ...
^L1.2 Abstraction
7
and ...
1.2.2 Abstraction by Specification
... ...
^LAn Overview of CLU
14
In addition to ...
2.1.2 Type Checking
...
(End text)
所需的输出是:
1.2.1 Abstraction by Parameters 6
1.2.2 Abstraction by Specification 7
2.1.2 Type Checking 14
我想要做的是提取第三级部分名称和它们出现的页码。
我想知道如何用Python编写程序来实现这一目标?
这是我到目前为止所想的:
^\s*\d+\.\d+\.\d+.*\n
^^L.*\n.*^\s*\d+\s*\n
我仍然不确定如何继续。谢谢你的启发!
答案 0 :(得分:1)
您需要分隔的字符是\x0C
/ ^L
/ chr(12)
,即Page Break个字符。
<强> Demo 强>
迭代方法
import re
def foo(lines):
name = ''
pages = []
page_break_char = chr(0xC)
for line in lines:
if re.match('^\s*\d+\.\d+\.\d+.*', line):
name = line
elif re.match('^\d+$', line):
pages.append(line)
elif page_break_char in line:
if name:
yield name, pages
del pages[:]
if name:
yield name, pages
<强>使用强>
text = '''
.. A language ...
\x0CIntroduction
6
A preferable alternative is ...
1.2.1 Abstraction by Parameters
Abstraction allows us, ...
\x0C1.2 Abstraction
7
and ...
1.2.2 Abstraction by Specification
... ...
\x0CAn Overview of CLU
14
In addition to ...
2.1.2 Type Checking ...
'''
lines = text.split('\n')
for name, pages in foo(lines):
print name, ' '.join(pages)
<强>输出强>
答案 1 :(得分:1)
你必须了解文本 - 我需要仔细检查以制作这个。页码看起来像 - FormFeedPageNoLineFeed
或LineFeedPageNoLineFeed
,并且页面上可以有多个第三级标题,所以从正则表达式开始,将提取整个页面并捕获页码
pages = re.compile(r'[\n\f](\d+)\n.*?(?=[\n\f](\d+)\n)', flags = re.DOTALL | re.MULTILINE)
然后在每个页面中搜索第三级标题并将它们放在一起。
third_level = re.compile('\n(\d+\.\d+\.\d+[^\n]*)')
for page in pages.finditer(s):
page_no = page.group(1)
for item in third_level.finditer(page.group()):
print '{}\t{}'.format(item.group(1), page_no)
这产生了54个第三级标题。不幸的是,它是您的文字所独有的。在我弄清楚这一点的时候,我可以用一个好的文本编辑器半手动提取信息,这个编辑器可以进行正则表达式搜索(这就是我做出来解决它并验证它的方法)。
您可以优化pages
- .*?
与前瞻断言相结合。
编辑以提取第一级和第二级标题,然后与第三级标题结合使用。 OP文件的唯一标识stuff.txt
import re
with open('stuff.txt') as f:
s = f.read()
提取内容和附录信息,附录分开提取以简化合并。
content_item = re.compile('\d+\.?\d*? [^\n]*')
appendix_item = re.compile('Appendix[^\n]*|[ABC]\.[^\n]*')
# Indices to limit the contents search
content_start = re.search('\f\fContents', s).span()[1]
content_end = re.search('\f\fPreface', s).span()[0]
content_items = content_item.findall(s, content_start, content_end)
appendices = appendix_item.findall(s, content_start, content_end)
现在找到所有第三级标题和页码 - 与上面相同,但存储在列表中,
third_level = re.compile('\n(\d+\.\d+\.\d+[^\n]*)')
pages = re.compile(r'[\n\f](\d+)\n.*?(?=[\n\f](\d+)\n)', flags = re.DOTALL | re.MULTILINE)
third_levels = list()
for page in pages.finditer(s, content_end):
page_no = page.group(1)
for item in third_level.finditer(page.group()):
third_levels.append('{}\t{}'.format(item.group(1), page_no))
合并内容和third_level标题,排序并添加附录标题。
a = content_items + third_levels
def key(item):
'''Extract digits from the beginning of item for a sort key.
item is a string
>>> key('1 ABC')
(1, None, None)
>>> key('1.2 ABC')
(1, 2, None)
>>> key('1.2.3 ABC')
(1, 2, 3)
>>>
'''
item = item.split()
item = item[0].split('.')
a, b, c = None, None, None
try:
a = int(item[0])
except ValueError as e:
pass
try:
b = int(item[1])
except IndexError as e:
pass
try:
c = int(item[2])
except IndexError as e:
pass
return a, b, c
a.sort(key = key)
a.extend(appendices)