Можно подумать, что синтаксический анализатор является излишеством для этой проблемы, но если вы используете один, то вам будет лучше в состоянии справиться с неизбежным «ой, есть еще один незначительные изменения в формате «изменения, которые придут.
Вот Pyparsing решение Вашего вопроса:
from pyparsing import Word, printables, ZeroOrMore, OneOrMore
hashword = Word('#', printables, min=2)("hashtag*")
word = ~hashword + Word(printables)
msg = (ZeroOrMore(word)("leading") +
hashword +
OneOrMore(word)("internal") +
hashword +
ZeroOrMore(hashword | word)("trailing"))
tests = """\
Hello #world I am in #London and it is #sunny today it is #2016
Hello #London I am in #London and it is #sunny today it is #2016
Hello #Austin I am at #SXSW and this is just a # hashtag symbol"""
msg.runTests(tests)
# show how to access the named results in the parsed output
for t in tests.splitlines():
fields = msg.parseString(t)
print(fields.hashtag)
hashword
определяет слово, начинающееся с «#», и имеет, по меньшей мере, один дополнительный символ. ("hashtag*")
будет служить для сбора всех хэштегов в сообщении в одно имя результата. word
определяет слово любых символов, если оно не является hashword
.Определение msg
определяет все части указанного вами сообщения и присваивает разные части именам leading
, internal
и trailing
.
Наконец, маленький цикл for-loop в конце показывает, как получить доступ к различным именованным результатам, возвращенным из вызова, до parseString()
.
Вот что это выводит:
Hello #world I am in #London and it is #sunny today it is #2016
['Hello', '#world', 'I', 'am', 'in', '#London', 'and', 'it', 'is', '#sunny', 'today', 'it', 'is', '#2016']
- hashtag: ['#world', '#London', '#sunny', '#2016']
- internal: ['I', 'am', 'in']
- leading: ['Hello']
- trailing: ['and', 'it', 'is', '#sunny', 'today', 'it', 'is', '#2016']
- hashtag: ['#sunny', '#2016']
Hello #London I am in #London and it is #sunny today it is #2016
['Hello', '#London', 'I', 'am', 'in', '#London', 'and', 'it', 'is', '#sunny', 'today', 'it', 'is', '#2016']
- hashtag: ['#London', '#London', '#sunny', '#2016']
- internal: ['I', 'am', 'in']
- leading: ['Hello']
- trailing: ['and', 'it', 'is', '#sunny', 'today', 'it', 'is', '#2016']
- hashtag: ['#sunny', '#2016']
Hello #Austin I am at #SXSW and this is just a # hashtag symbol
['Hello', '#Austin', 'I', 'am', 'at', '#SXSW', 'and', 'this', 'is', 'just', 'a', '#', 'hashtag', 'symbol']
- hashtag: ['#Austin', '#SXSW']
- internal: ['I', 'am', 'at']
- leading: ['Hello']
- trailing: ['and', 'this', 'is', 'just', 'a', '#', 'hashtag', 'symbol']
['#world', '#London', '#sunny', '#2016']
['#London', '#London', '#sunny', '#2016']
['#NewYork', '#SXSW']
EDIT
Если вы не уверены в том, что входная строка фактически содержит хештегов и слова в форме вы описываете, вы можете расширить парсер определение принимает практически любую комбинацию хэштегов и слов в качестве резервной копии:
msg = (ZeroOrMore(word)("leading") +
hashword +
OneOrMore(word)("internal") +
hashword +
ZeroOrMore(hashword | word)("trailing")
|
# use this expression to just get whatever hashtags are to be found
OneOrMore(hashword | word))
Вторая часть анализатора просто соберет все хэштеги в имя результата «hashtag», а остальные имена («ведущие» и т. д.) будут неопределенными.
Большое вам спасибо, единственная проблема в том, что этот метод не может заметить хэштеги, если они являются самым первым словом сообщений, например, если это «#Hello #worlds I am ...» !! – Far
Очистка логики оставлена как упражнение для вопроса плаката – PaulMcG
:) Конечно! спасибо за помощь, которую вы предоставили – Far