Необязательные символы в регулярном выражении

Задача довольно простая, но хорошего решения я пока не придумал: строка может содержать числа, тире и плюсы или только числа.

^[0-9+-]+$

делает большую часть того, что мне нужно, за исключением случаев, когда пользователь вводит мусор, например "+-+--+"

Мне не повезло с обычным просмотром вперед, поскольку тире и плюсы потенциально могут быть где угодно в строке.

Допустимые строки:

  1. 234654
  2. 24-3+-2
  3. -234
  4. 25485+

Неверный:

  1. ++--+

person Martin    schedule 19.05.2009    source источник
comment
Я нахожу ваши действительные строки странными. Не могли бы объяснить предысторию?   -  person VVS    schedule 19.05.2009
comment
Моим первым предположением были арифметические выражения, интерпретирующие 3+-+4 как 3 + (-(+4)). Но замыкающие плюсы и минусы не вписываются в эту картину.   -  person Daniel Brückner    schedule 19.05.2009


Ответы (5)


Как насчет:

^[0-9+-]*[0-9][0-9+-]*$

Это гарантирует, что где-то в строке есть хотя бы одна цифра. (Однако похоже, что у него может быть много возвратов. Но, с другой стороны, у него нет + или *, обернутых внутри другого + или *, что мне тоже не нравится.)

person Michael Myers    schedule 19.05.2009
comment
Опереди меня, моя точная мысль тоже. - person Ben S; 19.05.2009
comment
Но законно ли 2+++5? Это с вашим регулярным выражением. - person 0x6adb015; 19.05.2009
comment
Если 24-3+-2 допустимо (а так кажется), то я предполагаю, что 2+++5 тоже допустимо. - person Michael Myers; 19.05.2009
comment
2+++5 должно соответствовать описанию: строка может содержать числа, тире и плюсы или только числа. - person Ben S; 19.05.2009
comment
Что ж, в вопросе ничего не говорится о действительных математических выражениях. - person Jonathan Freeland; 19.05.2009
comment
Если ему нужны математические выражения, дерево выражений будет намного лучше, чем регулярное выражение. Но я заметил, что * и / не разрешены, поэтому я не думаю, что это должна быть математика. - person Michael Myers; 19.05.2009

Как насчет этого:

([+-]?\d[+-]?)+

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

Вот тестовый скрипт Python:

import re
TESTS = "234654 24-3+-2 -234 25485+ ++--+".split()
for test in TESTS:
    print test, ":", re.match(r'([+-]?\d[+-]?)+', test) is not None

который печатает это:

234654 : True
24-3+-2 : True
-234 : True
25485+ : True
++--+ : False
person RichieHindle    schedule 19.05.2009
comment
Почти хорошо! Единственная проблема заключается в том, что если вы добавите привязки к этому выражению следующим образом: ^([+-]?\d+[+-]?)+$ это приведет к Катастрофический поиск с возвратом при представлении несоответствующей строки, подобной этой: 01234567890123456789X Проблема в том, что это по существу: (\d+)+ что является рецептом катастрофы для механизма регулярных выражений с возвратом. Чтобы это исправить, просто удалите + из \d+ вот так: ^([+-]?\d[+-]?)+$ - прекрасно работает. Исправьте это, и вы получите мой +1. - person ridgerunner; 25.04.2011
comment
Добро пожаловать. Я узнал, что наиболее важно проверять случаи, которые не совпадают, — именно здесь скрывается большинство проблем. +1 - person ridgerunner; 25.04.2011

^([+-]*[0-9]+[+-]*)+$

Еще одно решение, использующее положительный взгляд на утверждение, гарантирующее наличие хотя бы одного числа.

^[0-9+-]+$(?<=[0-9][+-]*)

Или с помощью положительного взгляда вперед.

(?=[+-]*[0-9])^[0-9+-]+
person Daniel Brückner    schedule 19.05.2009
comment
^([+-]*[0-9]+[+-]*)+$ станет патологическим при несоответствии (см. мой комментарий к решению Ричи). ^[0-9+-]+$(?<=[0-9][+-]*) не будет работать, потому что он использует просмотр назад переменной длины (это есть только в .NET и JGSoft). (?=[+-]*[0-9])^[0-9+-]+ в порядке, но не нужно смотреть вперед - просто используйте ^[-+]*\d[\d+-]*$ напрямую. - person ridgerunner; 25.04.2011

я люблю

^(?=.*\d)[\d+-]+$ 

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

person tchrist    schedule 24.04.2011

Я бы сделал это так:

^[-+]*\d[\d+-]*$

Быстро это хорошо!

person ridgerunner    schedule 25.04.2011