Skip to main content
 首页 » 编程设计

python之使用正则表达式在 Python 中保留上下文的同时解析句子的一部分

2025年05月04日23qq78292959

我有很多 json 类(class),对于每门类(class),都有一个先决条件字段,其中包含该特定类(class)的先决条件列表,如下所示:

(为简单起见,我们只遵循 AAAA111 格式)

AAAA111, BBB111, CCC101, DDD104 

每门类(class)都遵循 \w{3,4}\d{3} 格式,因此在 Python 中使用正则表达式获取每门类(class)并不太难。

问题:

我不知道认为这是实现此目的的绝妙方法的天才是谁,但是在如何列出先决条件列表方面没有任何一致的格式。下面是我发现的一些列表示例格式:

AAAA111, BBB111, CCC101, and DDD104 
AAAA111, BBB111, CCC101 or DDD104 
AAAA111, AAAA112 or AAAA113, BBB333 
AAA111 or BBB111, AND CCC111 
AAA111 or BBB111 or CCC111 or DDD111 
AAA111 or 112 or 222 or 333 
AAA111 or instructor permission 
AAA111/221 
and so on... :( 

有数以千计的类(class),而且我发现了如此多不同的格式,以至于有时我想知道只要有怪人存在,是否最好手动完成所有内容。

因此,使用正则表达式提取提到的特定类(class)以解析与 \w{3,4}\d{3} 的匹配并不难。使用正则表达式匹配 or、and 或 instructor permission 等关键字的存在也不难。

我遇到的问题是保留上下文。

在上面的例子中:

AAAA111, BBB111, CCC101, and DDD104 

这样的先决条件列表意味着这门类(class)需要完成所有 4 门类(class)。

AAAA111, BBB111, CCC101 or DDD104 
AAA111 or 112 or 222 or 333 

这样的先决条件列表意味着这门类(class)只需要参加 4 门类(class)中的 1 门或更多门类(class)。

AAAA111, AAAA112 or AAAA113, BBB333 

但是对于这样的怪人...

我能做什么?显然,仅仅拥有一个在 或 或 and 或其他此类关键字出现时被激活的标志是行不通的。我坚持如何在保持上下文的同时最好地解析它。人类阅读这篇文章可以很容易地弄清楚上下文是什么,但是......

编辑:由于清晰度似乎是个问题,我会尽量在此处说得更清楚。 我想做的是为所有类(class)更改每门类(class)的每个先决条件类(class)列表,以便它们都具有 1 种一致的、编程可读的格式。

请您参考如下方法:

您可以尝试使用 pyparsing这是处理语法的好库。

如果条目具有一致的( bool )逻辑,并且您知道如何解释 and 和 or 之间的逗号,那么您可以尝试使用以下方法解析条目基于 simpleBool.py 的脚本来自 pyparsing 的示例:

import pprint 
import string 
 
from pyparsing import Word, nums, Literal, opAssoc, operatorPrecedence 
 
 
course_name = Word(string.ascii_uppercase + nums + "/") | Literal("instructor permission") 
comma_separator = Literal(',') 
comma_separator.setParseAction(lambda t:"&&") 
 
and_separator = Literal(', and') | Literal(', AND') | Literal('and')  | Literal('AND') 
and_separator.setParseAction(lambda t:"&&") 
 
or_separator = Literal('or') | Literal("OR") 
or_separator.setParseAction(lambda t:"||") 
 
course_line = operatorPrecedence(course_name, 
                            [ 
                                (and_separator, 2, opAssoc.LEFT,), 
                                (or_separator, 2, opAssoc.LEFT), 
                                (comma_separator, 2, opAssoc.LEFT,), 
                            ]) 
 
data = """AAAA111, BBB111, CCC101, and DDD104 
AAAA111, BBB111, CCC101 or DDD104 
AAAA111, AAAA112 or AAAA113, BBB333 
AAA111 or BBB111, AND CCC111 
AAA111 or BBB111 or CCC111 or DDD111 
AAA111 or 112 or 222 or 333 
AAA111 or instructor permission 
AAA111/221 
""" 
 
for line in data.splitlines(): 
    results = course_line.parseString(line) 
    print(line) 
    pprint.pprint(results.asList()[0]) 
    print() 

打印:

AAAA111, BBB111, CCC101, and DDD104 
['AAAA111', '&&', 'BBB111', '&&', ['CCC101', '&&', 'DDD104']] 
 
AAAA111, BBB111, CCC101 or DDD104 
['AAAA111', '&&', 'BBB111', '&&', ['CCC101', '||', 'DDD104']] 
 
AAAA111, AAAA112 or AAAA113, BBB333 
['AAAA111', '&&', ['AAAA112', '||', 'AAAA113'], '&&', 'BBB333'] 
 
AAA111 or BBB111, AND CCC111 
['AAA111', '||', ['BBB111', '&&', 'CCC111']] 
 
AAA111 or BBB111 or CCC111 or DDD111 
['AAA111', '||', 'BBB111', '||', 'CCC111', '||', 'DDD111'] 
 
AAA111 or 112 or 222 or 333 
['AAA111', '||', '112', '||', '222', '||', '333'] 
 
AAA111 or instructor permission 
['AAA111', '||', 'instructor permission'] 
 
AAA111/221 
'AAA111/221'