Добавить исключение к сложному регулярному выражению - PullRequest
4 голосов
/ 15 марта 2019

Существует очень сложное регулярное выражение.

Но у меня проблема с этим. Символы # и ++ удаляются, если после них есть буквы.

Вопрос : Как добавить исключение в текущее регулярное выражение для (токены C ++ и C #)?

Я использовал следующее регулярное выражение:

import re

text = 'Must-have skills: -.Net programming experience; -2 years experience in C++; C#/.Net, C++/.Net, C./.Net.'
text = re.sub(r'[!,.:;—](?= |$)', ' ', text)
print(re.sub(r'(?i)(?:(?!\.net\b|\b-\b)[^\w\s])+(?=[^\w\s]*\b)', ' ', text))

И у меня был следующий результат:

'Must-have skills   .Net programming experience   2 years experience in C++  C .Net  C .Net  C .Net '

Желаемый результат:

'Must-have skills   .Net programming experience   2 years experience in C++  C# .Net  C++ .Net  C .Net '

Текущие регулярные выражения

  • (?i) - режим без учета регистра включен
  • (?:(?!\.net\b|\b-\b)[^\w\s])+ - любой символ пунктуации ([^\w\s]), 1 или более вхождений, как можно больше, которые не запускают ни одну из последовательностей:
    • \.net\b - .net как целое слово
    • | - или
    • \b-\b - дефис, заключенный в слово chars
  • (?=[^\w\s]*\b) - положительный прогноз, требующий 0+ знаков препинания, за которыми следует позиция границы слова сразу справа от текущего местоположения.

Ответы [ 3 ]

3 голосов
/ 15 марта 2019

Редактировать

# 1

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

>>> import re

>>> text = 'Must-have skills: -.Net programming experience; -2 years experience in C++; C#/.Net, C++/.Net, C./.Net.'

>>> re.sub('(?:(?<!\S)|(?<=[\s\+\.C#]))[\-!,.:;—/]|[\-!,.:;—/](?=\s|$)', ' ', text)


#Output
'Must-have skills   .Net programming experience   2 years experience in C++  C# .Net  C++ .Net  C  .Net '

.

Объяснение

  • Ответ здесь фактически совпадает с ответом, приведенным ниже, но вместо того, чтобы объявлять символы, которые должны предшествовать захваченному набору, которые будут действовать один за другим, я определяю их всех в одном наборе.

.

# 2

Вид действительно грязного раствора, но

Выложу объяснение позже; может даже улучшить его для лучшей читаемости

>>> import re

>>> text = 'Must-have skills: -.Net programming experience; -2 years experience in C++; C#/.Net, C++/.Net, C./.Net.'

>>> re.sub('(?:(?<!\S)|(?<=\s)|(?<=\+)|(?<=\.)|(?<=C)|(?<=#))[\-!,.:;—/]|[\-!,.:;—/](?=\s|$)', ' ', text)


#Output
'Must-have skills   .Net programming experience   2 years experience in C++  C# .Net  C++ .Net  C  .Net '

.

Редактировать: Объяснение

  • Итак, открывая с помощью (?:, я открываю, говоря, что запросу, который я хочу захватить, в этом случае должен предшествовать набор перехвата, который содержит все, что определено непосредственно за (?:.
  • Ключевым моментом здесь является то, что указатели, начинающиеся с (?<! и (?<=, не могут быть установлены так, чтобы игнорировать диапазон значений, поэтому я должен сначала начать с (?:, а затем дать несколько (?<! и (?<= означает, что захваченному должен или не должен предшествовать этот символ, а НЕ предшествовать этому другому символу и т. Д. И т. Д.
  • Итак, открыв с помощью (?:, я теперь могу установить значения, которым должно быть или не должно предшествовать то, что захватывается
  • Начиная с (?<!\S), это действительно не нужно, но я включил его, потому что он бросает страховочную сетку. В основном говорится, что диапазон [\-!,.:;—/] НЕ должен быть захвачен / задействован, если ему предшествует какой-либо случайный непробельный символ
  • С |(?<=\s) Я говорю, что * ИЛИ [\-!,.:;—/] должен быть захвачен / активирован, если ему предшествует какой-либо один символ пробела
  • С |(?<=\+)|(?<=\.)|(?<=C) Я говорю ИЛИ [\-!,.:;—/] должно быть захвачено / активировано, если ему предшествуют +,., Или C, , поэтому \. OR just . [a period] в [\-!,.:;—/] будет захватить / выполнить действие, если ему предшествует C, как в вашей строке (помните (?<=C)); и ; в [\-!,.:;—/] будет захвачено / выполнено, если ему предшествует + (помните (?<=\+)).
  • Финальный ) до | закрытия (?:.
  • | как вы знаете, ИЛИ, и, поскольку я не могу сделать заявление «все в одном», я должен переопределить [\-!,.:;—/], а затем оглянуться на следующее: «1093 * Захватить / действовать на [\-!,.:;—/] если за ним следуют пробел или конец строки. С помощью lookaheads вы можете определять обычные однорядные строковые типы 'диапазонов', чтобы вы могли фактически использовать OR statements внутри них, но вы не можете при использовании lookaheads
3 голосов
/ 15 марта 2019

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

text = 'Must-have skills: -.Net programming experience; -2 years experience in C++; C#/.Net, C++/.Net, C./.Net.'
text = re.sub(r'(?i)(?:(?!\.net\b|\b-\b)(?<!C)(?<!C\+)[^\w\s])+(?=[^\w\s]*\b)', ' ', text)
text = re.sub('[!,.:;—](?= |$)', ' ', text)

Вывод:

print(text)
Must-have skills   .Net programming experience   2 years experience in C++  C# .Net  C++ .Net  C  .Net 
2 голосов
/ 16 марта 2019

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

Таким образом, вы можете расширить шаблонс делами, которые вы хотите сохранить или хотите удалить.При замене вы используете группу захвата.Вместо встроенного модификатора (?i) вы можете также использовать re.IGNORECASE в коде.

(c(?:\+{2}|#)|\.net\b)|[!,.:;/—]|-(?=[\d.])

Это будет соответствовать:

  • ( Группа захвата
    • c(?:\+{2}|#)|\.net\b Соответствует c ++ или c # или .net
  • ) Закрыть группу захвата
  • | Или
  • [!,.:;/—]Соответствует любому из перечисленных в классе символов
  • | Или
  • -(?=[\d.]) Соответствует дефису, утверждающему, что непосредственно справа является цифра или точка

Regex demo | Python demo

Например

import re
regex = r"(c(?:\+{2}|#)|\.net\b)|[!,.:;/—]|-(?=[\d.])"
text = 'Must-have skills: -.Net programming experience; -2 years experience in C++; C#/.Net, C++/.Net, C./.Net.'
text = re.sub(regex, r"\1 ", text, 0, re.IGNORECASE)

if text:
    print (text)

# Must-have skills   .Net  programming experience   2 years experience in C++   C#  .Net   C++  .Net   C  .Net 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...