Обработка RegEx с помощью Python - PullRequest
1 голос
/ 28 июня 2019

Я пытаюсь изучать python и одновременно выполнять анализ текста с использованием NLTK.

Я использую python для очистки текста перед анализом текста.

Учитывая предложение: The target IP was: 127.1.1.100.

Я хочу разбить его на:

["The", "target", "IP", "was", ":","127.1.1.100","."]

Важно, чтобы я сохранил все знаки препинания, чтобы восстановить исходный документ, но мне нужно разделить начальную / конечную пунктуацию, чтобы я мог анализировать отдельные слова.Я написал следующий код на Python, который отлично работает, но выглядит немного глупо.

punct = ['.', ',', ':', ';', '!', '[', ']', '(', ')', '{', '}']
def split_punctuation(sentence)-> list:
    sentwords = sentence.split(" ")
    for i, word in enumerate(sentwords):
        if word_ends_with_punct(word) and len(word) > 1:
            sentwords.pop(i)
            sentwords.insert(i, word[:-1])
            sentwords.insert(i+1, word[-1])
            word = word[:-1]
        if word_starts_with_punct(word) and len(word) > 1:
            sentwords.pop(i)
            sentwords.insert(i, word[0:1])
            sentwords.insert(i+1, word[1:])
            word = word[1:]
    return sentwords

def word_starts_with_punct(w)-> bool:
    for p in punct:
        if w.startswith(p):
            return True
    return False

def word_ends_with_punct(w)->bool:
    for p in punct:
        if w.endswith(p):
            return True
    return False

Итак, глядя на SO, я нашел регулярное выражение, которое делает то, что я хочу, вроде ... RegEx от Wiktor Stribiżew

re.sub(r'[]!"$%&\'()*+,./:;=#@?[\\^_`{|}~-]+', r' \g<0> ', my_text).strip()

Мне удалось выяснить, что происходит, но в этой форме он разделяет ВСЕ знаки препинания даже в середине слова.Например, она преобразует текущую дату из: 6/28/2109 в "6 / 28 / 2019".

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

def sep_punct_by_regex(sent)->list :
    words = sent.split(" ")
    new_words = []
    for w in words:
        tmp1 = re.sub(r'^[]!"$/%&\'()*+,.:;=#@?[\\^_`{|}~-]+', r' \g<0> ', w).strip()
        tmp2 = re.sub(r'[]!"$/%&\'()*+,.:;=#@?[\\^_`{|}~-]+$', r' \g<0> ', tmp1).strip()
        t = tmp2.split(" ")
        for x in t:
            new_words.append(x)
    return new_words

Обратите внимание на ^ в tmp1 и $ в tmp2. Это работает как есть, но цель состоит в том, чтобы научиться при сборке, как мне изменитьRegEx для одного прохода?Я попробовал очевидное (^) заранее и $ в конце, но это не работает.

1 Ответ

1 голос
/ 28 июня 2019

Вы можете использовать

re.findall(r'\b(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(?:\.(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}\b|[^\W_]+|(?:[^\w\s]|_)+', s)

См. Демонстрационный пример regex

Чтобы удалить пунктуацию на обоих концах строки и полосы из пробелов, используйте

re.sub(r'^[\W_]+|[\W_]+$', '', s).strip()

Итак, это будет выглядеть как

s = re.sub(r'^[\W_]+|[\W_]+$', '', s).strip()
oct = r'(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])'
return re.findall(r'\b{0}(?:\.{0}){{3}}\b|[^\W_]+|(?:[^\w\s]|_)+'.format(oct), s)

Подробности

  • \b(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(?:\.(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}\b - шаблон регулярного выражения IPv4
  • | - или
  • [^\W_]+ - одна или несколько букв или цифр
  • | - или
  • (?:[^\w\s]|_)+ - один илибольше символов, кроме слов и пробелов или _.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...