Python Regex - Позиции и значения совпадений текста Unicode - PullRequest
0 голосов
/ 30 января 2019

Я должен сопоставить множественные вхождения токенов в документе и получить значение и позицию соответствующего токена.

Для текста не в кодировке Юникод я использую это регулярное выражение r"\b(?=\w)" + re.escape(word) + r"\b(?!\w)" с finditerи это работает.

Для текста в Юникоде я должен использовать решение, подобное границе слова, например u"(\s|^)%s(\s|$)" % word.Это будет работать в большинстве случаев, но не тогда, когда у меня есть два последовательных слова, как в «तुम मुझे दोस्त कहते कहते हो».

Это код для воспроизведения этой проблемы.

import re
import json

# a input document of sentences
document="These are oranges and apples and and pears, but not pinapples\nThese are oranges and apples and pears, but not pinapples"


# uncomment to test UNICODE
document="तुम मुझे दोस्त कहते कहते हो"

sentences=[] # sentences
seen = {} # map if a token has been see already!

# split into sentences
lines=document.splitlines()

for index,line in enumerate(lines):

  print("Line:%d %s" % (index,line))

  # split token that are words
  # LP: (for Simon ;P we do not care of punct at all!
  rgx = re.compile("([\w][\w']*\w)")
  tokens=rgx.findall(line)

  # uncomment to test UNICODE
  tokens=["तुम","मुझे","दोस्त","कहते","कहते","हो"]

  print("Tokens:",tokens)

  sentence={} # a sentence
  items=[] # word tokens

  # for each token word
  for index_word,word in enumerate(tokens):

    # uncomment to test UNICODE
    my_regex = u"(\s|^)%s(\s|$)"  % word
    #my_regex = r"\b(?=\w)" + re.escape(word) + r"\b(?!\w)"
    r = re.compile(my_regex, flags=re.I | re.X | re.UNICODE)

    item = {}
    # for each matched token in sentence
    for m in r.finditer(document):

      token=m.group()
      characterOffsetBegin=m.start()
      characterOffsetEnd=characterOffsetBegin+len(m.group()) - 1 # LP: star from 0

      print ("word:%s characterOffsetBegin:%d characterOffsetEnd:%d" % (token, characterOffsetBegin, characterOffsetEnd) )

      found=-1
      if word in seen:
        found=seen[word]

      if characterOffsetBegin > found:
        # store last word has been seen
        seen[word] = characterOffsetBegin
        item['index']=index_word+1 #// word index starts from 1
        item['word']=token
        item['characterOffsetBegin'] = characterOffsetBegin;
        item['characterOffsetEnd'] = characterOffsetEnd;
        items.append(item)
        break

  sentence['text']=line
  sentence['tokens']=items
  sentences.append(sentence)

print(json.dumps(sentences, indent=4, sort_keys=True))

print("------ testing ------")
text=''
for sentence in sentences:
  for token in sentence['tokens']:
    # LP: we get the token from a slice in original text
    text = text + document[token['characterOffsetBegin']:token['characterOffsetEnd']+1] + " "
  text = text + '\n'
print(text)

Специально для токена कहते Я получу такое же совпадение вместо следующего токена.

word: कहते  characterOffsetBegin:20 characterOffsetEnd:25
word: कहते  characterOffsetBegin:20 characterOffsetEnd:25

1 Ответ

0 голосов
/ 30 января 2019

Для текста, не относящегося к Юникоду, вы можете использовать более подходящее регулярное выражение, например

my_regex = r"(?<!\w){}(?!\w)".format(re.escape(word))

Ваше не будет работать, если word начинается с символа без слова.Отрицательный знак (?<!\w) не подходит для совпадения, если слева от текущего местоположения находится слово char, а знак отрицательного просмотра (?!\w) не совпадает, если справа от текущего местоположения есть слово char.

Вторая проблема с регулярным выражением Unicode состоит в том, что вторая группа использует пробел после слова, и поэтому она не доступна для последующего соответствия.Здесь удобно использовать обходные пути:

my_regex = r"(?<!\S){}(?!\S)".format(re.escape(word))

См. Это Демонстрация Python онлайн .

Отрицательный просмотр (?<!\S) не дает совпадения, если есть несимвол пробела, расположенный слева от текущего местоположения, и отрицательный знак (?!\S) проваливает сопоставление, если справа от текущего местоположения находится символ без пробелов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...