Python:关于解析人类可读文本的问题
我正在解析一些人类可读的科学文本,主要是化学方面的内容。我想把这些文本分解成一个个单词、科学术语(稍后会详细说明)和标点符号。
举个例子,我希望把“hello, world.”这段文本分成4个部分:1)“hello”;2)逗号;3)“world”;4)句号。注意,空格不需要特别处理。
问题出在“科学术语”上:这些是化学公式的名称,比如“1-methyl-4-phenylpyridinium”。任何学过化学的人都知道,这些公式可能会很长,还可能包含数字、连字符和逗号,有时甚至还有括号,但我认为可以安全地假设这些表达式中不能有空格。此外,我相信这些表达式必须以数字开头。我希望每个这样的表达式都能作为一个整体被处理。
目前我使用手动解析的方法,寻找那些以数字开头,并以空格、换行符或后面跟着空格或换行符的标点符号结尾的“文本块”。
我在想是否有聪明的解决方案(比如正则表达式或其他方法),可以按照上述要求来处理文本。我是在使用Python,但这可能适用于其他编程语言。
一个示例输入(内容可以忽略...):
“Hello. 1-methyl-4-phenylpyridinium is ultra-bad. However, 1-methyl-4-phenyl-1,2,3,6-tetrahydropyridine is worse。”
示例输出(每个部分单独一行):
Hello
.
1-methyl-4-phenylpyridinium
is
ultra
-
bad
.
However
,
1-methyl-4-phenyl-1,2,3,6-tetrahydropyridine
is
worse
.
3 个回答
可能有正则表达式可以解析你想要的内容,但我觉得这样写出来的代码不太容易读懂和维护。我建议你使用像ANTLR这样的解析器生成器。你可能需要放弃把化学描述当作一个单独的部分来处理的想法,因为这太复杂了。ANTLR甚至有调试工具,可以让你看到为什么它没有解析你认为应该解析的内容,而用正则表达式是做不到这一点的。
祝好,
Sebastiaan
我同意Sebastiaan Megens的看法,使用正则表达式可能是可行的,但对于不熟悉正则表达式的人来说,代码可能会变得难以阅读和维护。如果你选择继续使用Python(我觉得这是个不错的选择),我建议你使用pyparsing模块。
额外的可维护性在你需要解析的内容增长或变化时会非常有用。(我相信很多人会说“当”而不是“如果”!例如,有人已经评论说,你可能需要对化学名称的允许范围有更复杂的理解。也许在你选择工具之前,你的需求就已经在变化了!)
这段代码可以解决你现在的问题。如果你有更大的数据集,也可以稍微调整一下。
import re
splitterForIndexing = re.compile(r"(?:[a-zA-Z0-9\-,]+[a-zA-Z0-9\-])|(?:[,.])")
source = "Hello. 1-methyl-4-phenylpyridinium is ultra-bad. However, 1-methyl-4-phenyl-1,2,3,6-tetrahydropyridine is worse."
print "\n".join( splitterForIndexing.findall(source))
结果是:
"""
Hello
.
1-methyl-4-phenylpyridinium
is
ultra-bad
.
However
,
1-methyl-4-phenyl-1,2,3,6-tetrahydropyridine
is
worse
.
"""
抱歉,没注意到“超糟糕”这个词。如果需要把这些词分开的话……
import re
splitterForIndexing = re.compile(r"(?:[a-zA-Z]+)|(?:[a-zA-Z0-9][a-zA-Z0-9\-(),]+[a-zA-Z0-9\-()])|(?:[,.-])")
source = "Hello. 1-methyl-4-phenylpyridinium is ultra-bad. However, 1-methyl-4-phenyl-1,(2,3),6-tetrahydropyridine is worse."
print "\n".join( splitterForIndexing.findall(source))
给出的结果是:
"""
Hello
.
1-methyl-4-phenylpyridinium
is
ultra
-
bad
.
However
,
1-methyl-4-phenyl-1,(2,3),6-tetrahydropyridine
is
worse
.
"""