Найти префикс и суффикс ключевого слова с помощью pyparsing - PullRequest
0 голосов
/ 28 мая 2018

Я пытаюсь разобрать строки следующим образом: aa bb первый элемент ee ff

Мне нужен отдельный префикс ' aa bb ', ключевое слово: ' первый элемент 'и суффикс' ee ff '

Префикс и суффикс могут состоять из нескольких слов или даже не существовать.Ключевое слово - это список предопределенных значений.

это то, что я пробовал, но это не сработало:

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

Ответы [ 2 ]

0 голосов
/ 28 мая 2018

Первая проблема заключается в использовании вами оператора '&'.В pyparsing '&' создает Each выражений, которые похожи на And s, но принимают подвыражения в любом порядке:

Word('a') & Word('b') & Word('c')

будет соответствовать 'aaa bbb ccc', но также 'bbb aaa ccc',' ccc bbb aaa 'и т. д.

В вашем парсере вы захотите использовать оператор' + ', который выдает And выражений.And s соответствуют нескольким подвыражениям, но только в указанном порядке.

Во-вторых, одна из причин использования pyparsing заключается в том, чтобы принимать переменные пробелы.Пробелы являются проблемой для синтаксических анализаторов, особенно при использовании str.find или регулярных выражений - в регулярных выражениях это обычно проявляется в виде множества фрагментов \s+ во всех выражениях соответствия.В вашем синтаксическом анализаторе, если входная строка содержит 'first item' (два пробела между 'first' и 'item'), попытка сопоставить буквенную строку 'first item' не удастся.Вместо этого вы должны сопоставлять несколько слов по отдельности, возможно, используя класс Keyword pyparsing, и позволить pyparsing пропустить любой пробел между ними.Чтобы упростить это, я написал короткий метод wordphrase:

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

prints:

{{"first" "item"} | {"second" "item"}}

, указывающий, что каждое слово будет анализироваться индивидуально с любым количеством пробелов между словами.

Наконец, вы должны написать синтаксический анализатор, зная, что синтаксический анализ не выполняет никаких действий.В вашем синтаксическом анализаторе префиксное выражение ZeroOrMore(Word(alphas)) будет соответствовать всем словам в слове «aa bb first item ee ff» - тогда не останется ничего, чтобы соответствовать выражению ключевых слов, поэтому синтаксический анализатор завершится ошибкой.Чтобы закодировать это в pyparsing, вы должны написать в вашем ZeroOrMore выражение для префиксных слов, которое переводится как «соответствует каждому слову альфа, но сначала убедитесь, что мы не собираемся анализировать выражение ключевого слова».В pyparsing этот вид негативного просмотра реализован с помощью NotAny, который можно создать с помощью унарного оператора ~.Для удобства чтения мы будем использовать keywords выражение сверху:

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'
0 голосов
/ 28 мая 2018

Если я правильно понял ваш вопрос, это должно сработать:

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
...