Регулярное выражение Python: отклонить одно двузначное число и принять другие двузначные числа

1

Как заставить регулярное выражение не соответствовать определенному числу с более чем двумя цифрами. например, любое число, но 13. Вторая строка кода ниже не работает, она не будет соответствовать 10, 11,... и третья строка будет искать число, не начинающееся с 1, но имеющее 3:

str = 'val=13'

regex = 'val=[^1][^3]'
regex = 'val=[^13]

re.search(regex, str)
  • 0
    Откуда поступают данные? Если он не анализируется из файла, хорошей идеей может быть избегание регулярных выражений, как указывали другие.
  • 0
    Является ли строка большим текстом с несколькими значениями val=dd ? Всегда ли имя переменной "val" ? Может ли быть пробел вокруг знака равенства? Будет ли число когда-либо отрицательным?
Показать ещё 2 комментария
Теги:

6 ответов

0
Лучший ответ

Изменить: Изменено для соответствия номерам, имеющим одну или несколько цифр.

Если вам нужно выщипывать различные формы val=dd, где dd должно быть числом с одной или несколькими цифрами, а это число не может быть 13 (или -13), и может быть пробел, окружающий знак равенства, и номер может иметь необязательный знак +/-, тогда этот script показывает один из способов сделать это:

import re
# Regex: VERBOSE, commented version.
reLong = r"""
    # Match "val=dd" where dd has two or more digits (but is not 13).
    \bval\s*=\s*  # "val=" literal with optional ws.
    (?!           # Begin negative lookahead assertion.
      [+\-]?      # Number may have optional sign.
      13          # This is the number we don't match
      \b          # which ends on a word boundary.
    )             # The number is not 13, +13 or -13.
    (             # $1: Two digit number.
      [+\-]?      # Allow optional sign.
      \d+         # One or more digits.
    )             # End $1: containing 2 digit number
    """
# Regex: short, uncommented version.
reShort = r"\bval\s*=\s*(?![+\-]?13\b)([+\-]?\d{2}\b)"

# Compile a regex object we can use over and over.
reObj = re.compile(reLong, re.IGNORECASE | re.VERBOSE)

# Test data strings. Positive and negative. With/without whitespace.
input = [
    # String with positive numbers. No whitespace.
    "val=1 val=13, val=133, val=12, otherval=1",
    # String with positive numbers. With whitespace.
    "val = 1 val = 13, val = 133, val = 12, otherval = 1",
    # String with negative numbers. No whitespace.
    "val=-1 val=-13, val=-133, val=-12, otherval=-1",
    # String with negative numbers. With whitespace.
    "val = -1 val = -13, val = -133, val = -12, otherval = -1",
    ]

# Parse all test data strings and print matches.
for str in input:
    matches = reObj.findall(str)
    if matches:
        print(matches)

Регулярное выражение представлено в короткой и длинной подробной форме с комментариями. Вот результат из script:

['1', '133', '12']
['1', '133', '12']
['-1', '-133', '-12']
['-1', '-133', '-12']

Дополнительно: Чтобы соответствовать чему-то, что НЕ является чем-то более чем одним символом, мы используем отрицательный результат. Например, если вы хотите совместить слова, которые НЕ "BAD", вот комментированное регулярное выражение, которое показывает, как:

reobj = re.compile(r"""
    # Match a word that is not: 'BAD'
    \b         # Anchor to start of word.
    (?!BAD\b)  # Verify that this word is not 'BAD'
    \w+        # Ok. Safe to match non-BAD word.
    \b         # Anchor to end of word.
    """, re.VERBOSE)
  • 0
    Это не будет соответствовать val = 1 или val = 133
  • 0
    @Siavash M: Да, он соответствует val=133 но нет, он не соответствует val=1 потому что я понимаю, что вы хотите сопоставлять только цифры, имеющие две или более цифр. Какое количество цифр вы хотите сопоставить? (Его легко исправить.)
Показать ещё 2 комментария
5

Используйте утверждения lookahead:

In : re.findall('val=(?!13$)(\d{2,})', 'val=12') 
Out: ['12']

In : re.findall('val=(?!13$)(\d{2,})', 'val=13') 
Out: []
  • 0
    Должно быть (?13$) противном случае val=133 тоже блокируется.
  • 0
    ты абсолютно прав :) спасибо
Показать ещё 4 комментария
3

Некоторые люди, столкнувшись с проблемой, думают "Я знаю, я буду использовать регулярные выражения".

Теперь у них есть две проблемы.

Не используйте регулярные выражения для таких вещей:

str = "val=13"
num = int(str.split("=")[1])

# a two-digit number ranges from 10 - 99
if 10 <= num <= 99 and num != 13:
    print("Success!")
  • 0
    в общем, я бы согласился, но в этом особом случае это легко читаемый лайнер с регулярным выражением
  • 1
    Хм, вы можете сформулировать это по-другому: «Некоторые люди просто не получают синтаксис регулярных выражений, поэтому они стараются избегать его в любом случае. Теперь они импортируют 20-мегабайтную библиотеку синтаксического анализа, 10-мегабитную лексическую библиотеку и пишут 2000 строк Код. Маленького регулярного выражения было бы достаточно, но нет, регулярное выражение - зло !!!!!! 11111 ". -1
Показать ещё 2 комментария
3

Зачем вам нужно регулярное выражение?

>>> string = 'val=13'
>>> array=string.split("=")
>>> if array[0] == "val" and int(array[1]) < 100 and int(array[1]) == 13
...     print "match"
...
>>>

И все это предполагает, что я понял, что вы написали.

  • 2
    вам нужно int() вокруг числовых сравнений
  • 0
    @mike, да, спасибо за напоминание.
Показать ещё 1 комментарий
2

Если вам действительно нужно регулярное выражение, которое соответствует двум цифрам, кроме 13, это должно работать:

>>> str = 'val=13'
>>> regex = 'val=(?!13$)(\d{2,})'
>>> re.search(regex,str)
>>> str = 'val=26'
>>> re.search(regex,str)
<_sre.SRE_Match object at 0xb75c0bf0>

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

  • 0
    Хороший. Я бы посчитал этот вопрос скорее теоретическим, чем практическим. Ваш ответ правильный.
  • 1
    @MarcoS, ваш ответ не соответствует 10
Показать ещё 6 комментариев
0

Вы можете использовать "отрицательный взгляд вперед":

p = re.compile("val=(?!13)[0-9]{2}")
assert not p.match('val=13')
assert p.match('val=23')

Ещё вопросы

Сообщество Overcoder
Наверх
Меню