Я новичок в регулярных выражениях и потратил довольно много времени на эксперименты с тестерами регулярных выражений, поиск в Интернете и т. Д. По следующей проблеме. Я использую Python 3.7+.

Пример текстовой строки:

((AC00001234 + AC00005678) / 365) * (5 + 10)

Примечание. AC всегда в верхнем регистре, за которым следует ровно 8 цифр.

Желаемый результат: подобранная группа со следующими элементами. Точнее, любые и все номера без префикса AC.

  • 365
  • 5
  • 10

Хотя я перепробовал больше вещей, чем могу сосчитать, я подошел ближе всего с негативным взглядом назад (ниже). Проблема в том, что результат также набирает 00001234 и 00005678. Я пробовал явные классы символов [0-9], настраивал некоторые группировки и т. Д.

Текущий код:

(?

Текущий результат:

  • 00001234
  • 00005678
  • 365
  • 5
  • 10

В Stack Overflow я посмотрел на следующее: Отрицательный просмотр назад в регулярном выражении с необязательным префиксом, Шаблон соответствия без предшествующей или последующей строки, Автономные числа Regex? и Regex для определения отдельных номеров.

Для простоты я разбил синтаксический анализ на три других шага (например, извлечение только кодов префикса AC, математических операторов и т. Д.), И эта часть является последней, которую мне нужно решить.

1
AIphanumeric425 17 Сен 2020 в 01:44

2 ответа

Лучший ответ

Очевидный способ сделать это: (?<!AC)\d+ - набор цифр, перед которым не стоит AC. Однако это не удается, потому что он соответствует 0001234, поскольку ему предшествует 0, а не AC. Недостаток состоит в том, что вы также должны утверждать, что ему не предшествует цифра:

(?<!AC)(?<!\d)\d+

В зависимости от возможных входных строк утверждение границы слова также может выполнять аналогичную работу:

(?<!AC)\b\d+

Ваш код ((?<!AC\d{8})\d+) не работает, потому что он означает "набор цифр, перед которым не стоит ACXXXXXXXX (где X - цифра). AC00001234 не предшествует AC и еще восемь цифр, поэтому это совпадение. Вы могли бы исправить это, заявив его после совпадения: \d+(?<!AC\d{8}), но это не удается по той же причине - 00001234 будет дисквалифицирован, но он не дисквалифицирует 0000123, потому что перед его концом нет AC и восьми цифр - только семь! так что вам все равно нужно граничное утверждение:

\d+(?<!AC\d{8})\b

Однако это менее ясно, чем первые два решения (а также требует, чтобы вы знали длину строки ACXXXXXXXX).

0
Amadan 16 Сен 2020 в 22:56

Вы можете использовать лучший трюк с регулярным выражением: сопоставить {{X0} } или AC\d{8} (или даже \bAC\d{8}(?!\d), если AC не может предшествовать какой-либо букве, цифре или подчеркиванию и не должно быть другой цифры после 8 цифр) вхождения шаблона и совпадение и захватите любые другие фрагменты цифр:

AC\d{8}|(\d+)

См. эту демонстрацию регулярных выражений, значения, выделенные зеленым цветом, - это то, что вам нужно с {{X0 }} в Python (этот метод возвращает только захваченные подстроки):

import re
text = "((AC00001234 + AC00005678) / 365) * (5 + 10)"
results = list(filter(None, re.findall(r'AC\d{8}|(\d+)', text)))
print( results )  # => 

list(filter(None, ...)) удаляет пустые элементы, которые обычно появляются, когда совпадает первая альтернатива (та, которую нам нужно опустить).

См. демонстрацию Python.

0
Wiktor Stribiżew 17 Сен 2020 в 11:46