Python 使用pyparsing查找关键字的前缀和后缀

Python 使用pyparsing查找关键字的前缀和后缀,python,pyparsing,Python,Pyparsing,我试图解析如下字符串:aa bb first item ee ff 我需要单独的前缀'aa bb',关键字:'first item'和后缀'ee ff' 前缀和后缀可以是几个单词,甚至不存在。关键字是预定义值的列表 这是我尝试过的,但没有成功: a = ZeroOrMore(Word(alphas)('prefix')) & oneOf(['first item', 'second item'])('word') & ZeroOrMore(Word(alphas)('suffix

我试图解析如下字符串:aa bb first item ee ff

我需要单独的前缀'aa bb',关键字:'first item'和后缀'ee ff'

前缀和后缀可以是几个单词,甚至不存在。关键字是预定义值的列表

这是我尝试过的,但没有成功:

a = ZeroOrMore(Word(alphas)('prefix')) & oneOf(['first item', 'second item'])('word') & ZeroOrMore(Word(alphas)('suffix'))

如果我正确理解了你的问题,这应该可以做到:

toParse='aa bb first item ee ff'
keywords=['test 1','first item','test two']
for x in keywords:
    res=toParse.find(x)
    if res>=0:
        print('prefix='+toParse[0:res])
        print('keyword='+x)
        print('suffix='+toParse[res+len(x)+1:])
        break
给出以下结果:

prefix=aa bb 
keyword=first item
suffix=ee ff

第一个问题是使用“&”运算符。在pyparsing中,&'生成每个表达式,这些表达式类似于AND,但接受任意顺序的子表达式:

Word('a') & Word('b') & Word('c')
将匹配“aaa bbb ccc”,但也会匹配“bbb aaa ccc”、“ccc bbb aaa”等

在解析器中,您需要使用“+”运算符,它生成和表达式。AND匹配多个子表达式,但仅按给定顺序匹配

其次,使用pyparsing的原因之一是接受不同的空格。对于解析器来说,空白是一个问题,尤其是在使用str.find或regex时-在regex中,这通常表现为整个匹配表达式中的大量\s+片段。在pyparsing解析器中,如果输入字符串包含“first item”,则在“first”和“item”之间有两个空格,尝试匹配文本字符串“first item”将失败。相反,您应该分别匹配多个单词,可能使用pyparsing的关键字类,并让pyparsing跳过它们之间的任何空格。为了简化这一点,我写了一个简短的方法短语:

印刷品:

{{"first" "item"} | {"second" "item"}}
表示每个单词将被单独解析,单词之间有任意数量的空格

最后,您必须编写pyparsing解析器,知道pyparsing不做任何前瞻性工作。在您的解析器中,前缀表达式ZeroOrMoreWordalphas将匹配aa bb first item ee ff中的所有单词-然后没有任何内容可以匹配关键字表达式,因此解析器失败。要在pyparsing中编写此代码,您必须在ZeroOrMore中为前缀词编写一个表达式,该前缀词将转换为与Alpha的每个词匹配,但首先确保我们不打算解析关键字表达式。在pyparsing中,这种负前瞻是使用NotAny实现的,您可以使用一元~operator创建NotAny。为了便于阅读,我们将使用上面的关键字表达式:

non_keyword = ~keywords + Word(alphas)
a = ZeroOrMore(non_keyword)('prefix') + keywords('word') + ZeroOrMore(Word(alphas))('suffix')
下面是一个完整的解析器,以及对不同样本字符串使用runTests的结果:

def wordphrase(s):
    return And(map(Keyword, s.split())).addParseAction(' '.join)
keywords = wordphrase('first item') | wordphrase('second item')

non_keyword = ~keywords + Word(alphas)
a = ZeroOrMore(non_keyword)('prefix') + keywords('word') + ZeroOrMore(Word(alphas))('suffix')

text = """
    # prefix and suffix
    aa bb first item ee ff

    # suffix only
    first item ee ff

    # prefix only
    aa bb first item

    # no prefix or suffix
    first item

    # multiple spaces in item, replaced with single spaces by parse action
    first   item
    """

a.runTests(text)
给出:

# prefix and suffix
aa bb first item ee ff
['aa', 'bb', 'first item', 'ee', 'ff']
- prefix: ['aa', 'bb']
- suffix: ['ee', 'ff']
- word: 'first item'

# suffix only
first item ee ff
['first item', 'ee', 'ff']
- suffix: ['ee', 'ff']
- word: 'first item'

# prefix only
aa bb first item
['aa', 'bb', 'first item']
- prefix: ['aa', 'bb']
- word: 'first item'

# no prefix or suffix
first item
['first item']
- word: 'first item'

# multiple spaces in item, replaced with single spaces by parse action
first   item
['first item']
- word: 'first item'

谢谢你的解决方案。这个问题只是我任务的一部分。我需要解析复杂的字符串,这就是为什么我需要像PyParsing这样的语法分析器来解析复杂字符串的原因非常感谢你,Paul!你真棒!
# prefix and suffix
aa bb first item ee ff
['aa', 'bb', 'first item', 'ee', 'ff']
- prefix: ['aa', 'bb']
- suffix: ['ee', 'ff']
- word: 'first item'

# suffix only
first item ee ff
['first item', 'ee', 'ff']
- suffix: ['ee', 'ff']
- word: 'first item'

# prefix only
aa bb first item
['aa', 'bb', 'first item']
- prefix: ['aa', 'bb']
- word: 'first item'

# no prefix or suffix
first item
['first item']
- word: 'first item'

# multiple spaces in item, replaced with single spaces by parse action
first   item
['first item']
- word: 'first item'