Python 从多个列表中的多个元素中查找文本文件中的模式?

Python 从多个列表中的多个元素中查找文本文件中的模式?,python,regex,list,Python,Regex,List,我是一名初学者,作为我的第一种编程语言,我已经学习python几个月了。我想从文本文件中找到一个模式。我的第一次尝试是使用regex,它确实有效,但有一个限制: import re noun_list = ['bacon', 'cheese', 'eggs', 'milk', 'list', 'dog'] CC_list = ['and', 'or'] noun_list_pattern1 = r'\b\w+\b,\s\b\w+\b,\sand\s\b\w+\b|\b\w+\b,\s\b\w

我是一名初学者,作为我的第一种编程语言,我已经学习python几个月了。我想从文本文件中找到一个模式。我的第一次尝试是使用regex,它确实有效,但有一个限制:

import re

noun_list = ['bacon', 'cheese', 'eggs', 'milk', 'list', 'dog']
CC_list = ['and', 'or']

noun_list_pattern1 = r'\b\w+\b,\s\b\w+\b,\sand\s\b\w+\b|\b\w+\b,\s\b\w+\b,\sor\s\b\w+\b|\b\w+\b,\s\b\w+\b\sand\s\b\w+\b|\b\w+\b,\s\b\w+\b,\saor\s\b\w+\b'

with open('test_sentence.txt', 'r') as input_f:
    read_input = input_f.read()
    word = re.findall(noun_list_pattern1, read_input)
    for w in word:
        print w
else:
    pass
因此,在这一点上,您可能会问,既然这些列表没有被使用,为什么这些列表会出现在代码中。嗯,我一直在绞尽脑汁,尝试函数中的各种for循环和if语句,试图找到复制regex模式的原因,但使用列表

正则表达式的局限性在于,在“名词列表模式”中多次出现的
\b\w+\w\
代码实际上只查找单词(任何单词),而不查找特定的名词。这可能会导致误报。我想通过使用上面列表中的元素而不是正则表达式来缩小范围

由于我在regex模式中实际上有4个不同的regex(它包含4个
|
),所以我将在这里使用其中的1个。因此,我需要找到一种模式,例如:

名词列表中的名词“+”,“名词列表中的名词“+”,“抄送”列表中的“+”,“抄送”列表中的“+”,“抄送”列表中的“+”+”名词

显然,上面引用的代码行不是真正的python代码,而是我对所需匹配的想法的表达。我说的是名词列表中的名词,我指的是名词列表中的一个迭代C是通过CC_列表的迭代
是逗号和空格的文本字符串匹配

希望我已经说清楚了

下面是我正在使用的
test_-sensume.txt
文件的内容:

I need to buy are bacon, cheese and eggs. 
I also need to buy milk, cheese, and bacon.
What's your favorite: milk, cheese or eggs.
What's my favorite: milk, bacon, or eggs.

把你的问题分解一下。首先,你需要一个模式来匹配你列表中的单词,而不是其他。您可以使用交替运算符
|
和文字来完成这一点<例如,代码>红色|绿色|蓝色,将匹配
“红色”
“绿色”
、或
“蓝色”
,但不匹配
“紫色”
。将名词列表与该字符连接起来,并添加单词边界元字符和圆括号,以对备选字符进行分组:

noun_patt = r'\b(' + '|'.join(nouns) + r')\b'
对连词列表执行相同的操作:

conj_patt = r'\b(' + '|'.join(conjunctions) + r')\b'
您要进行的整体匹配是“一个或多个
noun\u patt
match,每个可选后跟一个逗号,后跟
conj\u patt
的匹配,然后再匹配一个
noun\u patt
match”。对于正则表达式来说非常简单:

patt = r'({0},? )+{1} {0}'.format(noun_patt, conj_patt)
您并不是真的想使用
re.findall()
,而是
re.search()
,因为每行只需要一个匹配项:

for line in lines:
...     print re.search(patt, line).group(0)
... 
bacon, cheese and eggs
milk, cheese, and bacon
milk, cheese or eggs
milk, bacon, or eggs

值得注意的是,就解析英语而言,您已经接近了正则表达式的极限。任何比这更复杂的问题,您都需要研究实际的解析,可能是使用NLTK。

稍微分解一下您的问题。首先,你需要一个模式来匹配你列表中的单词,而不是其他。您可以使用交替运算符
|
和文字来完成这一点<例如,代码>红色|绿色|蓝色,将匹配
“红色”
“绿色”
、或
“蓝色”
,但不匹配
“紫色”
。将名词列表与该字符连接起来,并添加单词边界元字符和圆括号,以对备选字符进行分组:

noun_patt = r'\b(' + '|'.join(nouns) + r')\b'
对连词列表执行相同的操作:

conj_patt = r'\b(' + '|'.join(conjunctions) + r')\b'
您要进行的整体匹配是“一个或多个
noun\u patt
match,每个可选后跟一个逗号,后跟
conj\u patt
的匹配,然后再匹配一个
noun\u patt
match”。对于正则表达式来说非常简单:

patt = r'({0},? )+{1} {0}'.format(noun_patt, conj_patt)
您并不是真的想使用
re.findall()
,而是
re.search()
,因为每行只需要一个匹配项:

for line in lines:
...     print re.search(patt, line).group(0)
... 
bacon, cheese and eggs
milk, cheese, and bacon
milk, cheese or eggs
milk, bacon, or eggs

值得注意的是,就解析英语而言,您已经接近了正则表达式的极限。如果比这更复杂,您将需要研究实际的解析,可能是使用NLTK。

实际上,您不一定需要正则表达式,因为有许多方法可以使用原始列表来完成

noun_list = ['bacon', 'cheese', 'eggs', 'milk', 'list', 'dog']
conjunctions = ['and', 'or']

#This assumes that file has been read into a list of newline delimited lines called `rawlines`
for line in rawlines:
    matches = [noun for noun in noun_list if noun in line] + [conj for conj in conjunctions if conj in line]
    if len(matches) == 4:
        for match in matches:
            print match
匹配号为4的原因是4是正确的匹配数。(注意,重复的名词或连词也可能出现这种情况)

编辑:

此版本打印匹配的行和匹配的单词。还修复了可能的多词匹配问题:

words_matched = []
matching_lines = []

for l in lst:
    matches = [noun for noun in noun_list if noun in l] + [conj for conj in conjunctions if conj in l]
    invalid = True
    valid_count = 0
    for match in matches:
        if matches.count(match) == 1:
            valid_count += 1
    if valid_count == len(matches):
        invalid = False

    if not invalid:
        words_matched.append(matches)
        matching_lines.append(l)

for line, matches in zip(matching_lines, words_matched):
    print line, matches
但是,如果这不适合您,您可以按如下方式构建正则表达式(使用
itertools
模块):

该方法的警告是,它是纯暴力的,因为它生成两个列表的所有可能组合(读取排列),然后可以测试这两个列表,看看每一行是否匹配。因此,它的速度非常慢,但在本例中,如果匹配给定的值(连词前的非逗号),则该将生成完全精确的匹配


根据需要进行调整。

实际上,您不一定需要正则表达式,因为有很多方法可以使用原始列表来实现这一点

noun_list = ['bacon', 'cheese', 'eggs', 'milk', 'list', 'dog']
conjunctions = ['and', 'or']

#This assumes that file has been read into a list of newline delimited lines called `rawlines`
for line in rawlines:
    matches = [noun for noun in noun_list if noun in line] + [conj for conj in conjunctions if conj in line]
    if len(matches) == 4:
        for match in matches:
            print match
匹配号为4的原因是4是正确的匹配数。(注意,重复的名词或连词也可能出现这种情况)

编辑:

此版本打印匹配的行和匹配的单词。还修复了可能的多词匹配问题:

words_matched = []
matching_lines = []

for l in lst:
    matches = [noun for noun in noun_list if noun in l] + [conj for conj in conjunctions if conj in l]
    invalid = True
    valid_count = 0
    for match in matches:
        if matches.count(match) == 1:
            valid_count += 1
    if valid_count == len(matches):
        invalid = False

    if not invalid:
        words_matched.append(matches)
        matching_lines.append(l)

for line, matches in zip(matching_lines, words_matched):
    print line, matches
但是,如果这不适合您,您可以按如下方式构建正则表达式(使用
itertools
模块):

该方法的警告是,它是纯暴力的,因为它生成两个列表的所有可能组合(读取排列),然后可以测试这两个列表,看看每一行是否匹配。因此,它的速度非常慢,但在本例中,如果匹配给定的值(连词前的非逗号),则该将生成完全精确的匹配


根据需要进行调整。

您可以发布一个您想要匹配的数据示例吗