Регулярное выражение для соответствия слов, начинающихся и заканчивающихся подчеркиванием с Python 3 - PullRequest
3 голосов
/ 05 марта 2019

У меня следующий пример кода, где я пытаюсь сопоставить все экземпляры слов, которые начинаются с и заканчиваются подчеркиванием (одинарным или двойным).

import re
test = ['abc text_ abc',
'abc _text abc',
'abc text_textUnderscored abc',
'abc :_text abc', 
'abc _text_ abc', 
'abc __text__ abc',
'abc _text_: abc',
'abc (-_-) abc']
test_str = ' '.join(test)
print(re.compile('(_\\w+\\b)').split(test_str))

Я уже пробовал следующее регулярное выражение, и оно кажется слишком сильным (должно соответствовать только _text_ и __text__).

Вывод: ['abc text_ abc abc ', '_text', ' abc abc text', '_textUnderscored', ' abc abc :', '_text', ' abc abc ', '_text_', ' abc abc ', '__text__', ' abc abc ', '_text_', ': abc abc (-_-) abc']

Можете ли вы предложить лучший подход (предпочтительно с одним шаблоном регулярных выражений и использованием метода re.split)?

Ответы [ 2 ]

2 голосов
/ 06 марта 2019

Если вы хотите сопоставить любые фрагменты символов слова (буквы, цифры и символы подчеркивания), которым не предшествуют и не следуют символы без слов (символы, отличные от букв, цифр и символов подчеркивания) и любой длины (даже 1, _) вы можете использовать

r'\b_(?:\w*_)?\b'

с re.findall. Смотрите regex demo .

Если вы не хотите сопоставлять одно-символьные слова (т. Е. _), вам нужно удалить необязательную группу без захвата и использовать r'\b_\w*_\b'.

Если вам нужно сопоставить хотя бы 3 символа, также замените * (ноль или более повторений) на + (одно или несколько вхождений).

Если вы рассматриваете слова как целые слова только тогда, когда они находятся в начале / конце строки или сопровождаются / предшествуют пробелам, замените \b...\b на (?<!\S)...(?!\S):

r'(?<!\S)_\w*_(?!\S)'

См. еще одну демонстрацию регулярных выражений

подробности

  • \b - граница слова, прямо перед
  • _ - подчеркивание
  • (?:\w*_)? - необязательная группа без захвата, соответствующая 1 или 0 вхождениям
    • \w* - 0+ слов (буквы, цифры, _ с) (благодаря этой необязательной группе будет найдено даже _ слово)
    • _ - подчеркивание
  • \b - граница слова, сразу после
  • (?<!\S) - левая граница пробела
  • (?!\S) - правая граница пробела

См. Демоверсию Python :

rx = re.compile(r'\b_(?:\w*_)?\b')
print(rx.findall(test_str))
# => ['_text_', '__text__']
1 голос
/ 06 марта 2019

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

def get_underscored(text):
    for word in text.split():
        if word.startswith("_") and word.endswith("_"):
            yield word

test = ['abc text_ abc',
'abc _text abc,',
'abc text_textUnderscored abc',
'abc :_text abc',
'abc _text_ abc',
'abc __text__ abc']
test_str = ' '.join(test)
print(list(get_underscored(test_str)))

Результат равен['_text_', '__text__'].

Разумеется, этот подход не масштабируется и не учитывает регулярные выражения для больших входов, он работает на несколько порядков быстрее для меньших.

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