В регулярном выражении, совпадают с тем или иным, или с обоими

В регулярном выражении мне нужно знать, как совпадать с тем или иным (или по порядку). Но по крайней мере одна из вещей должна быть там.

Например, следующее регулярное выражение

/^([0-9]+|\.[0-9]+)$/

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

234

и

.56

но не

234.56

В то время как следующее регулярное выражение

/^([0-9]+)?(\.[0-9]+)?$/

будет соответствовать всем трем строкам выше, но также будет соответствовать пустой строке, которую мы не хотим.

Мне нужно что-то, что будет соответствовать всем трем строкам выше, но не пустой строке. Есть ли простой способ сделать это?

UPDATE:

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

/^\s*-?0*(?:[0-9]+|[0-9]{1,3}(?:,[0-9]{3})+)(?:\.[0-9]*)?(\s*|[A-Za-z_]*)*$/

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

45
45.988
45,689
34,569,098,233
567,900.90
-9
-34 banana fries
0.56 points

но не будет соответствовать

.56

и мне нужно это сделать.

Ответы

Ответ 1

Полностью общий метод, заданный регулярными выражениями /^A$/ и /^B$/:

/^(A|B|AB)$/

то есть.

/^([0-9]+|\.[0-9]+|[0-9]+\.[0-9]+)$/

Обратите внимание, что другие использовали структуру вашего примера для упрощения. В частности, они (неявно) разложили его, чтобы вытащить общие факторы [0-9]* и [0-9]+ слева и справа.

Работа для этого:

  • все элементы конца чередования в [0-9]+, поэтому вытащите это: /^(|\.|[0-9]+\.)[0-9]+$/
  • Теперь у нас есть возможность пустой строки в чередовании, поэтому перезапишите ее с помощью ? (т.е. используйте эквивалентность (|a|b) = (a|b)?): /^(\.|[0-9]+\.)?[0-9]+$/
  • Опять же, чередование с общим суффиксом (\. на этот раз): /^((|[0-9]+)\.)?[0-9]+$/
  • шаблон (|a+) совпадает с a*, поэтому, наконец: /^([0-9]*\.)?[0-9]+$/

Ответ 2

Да, вы можете сопоставить все это с таким выражением:

/^[0-9]*\.?[0-9]+$/

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

Ответ 3

Конечно. Вам нужен дополнительный квантификатор ?.

/^(?=.)([0-9]+)?(\.[0-9]+)?$/

Вышеприведенное немного неудобно, но я хотел показать вам ваш точный шаблон с добавленным ?. В этой версии (?=.) гарантирует, что он не принимает пустую строку, так как я сделал оба предложения необязательными. Более простая версия:

/^\d*\.?\d+$/

Это удовлетворяет вашим требованиям, в том числе предотвращает пустую строку.

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

Изменить:

Если вы хотите совместить это с большей строкой, я рекомендую разделить и проверить результаты с помощью /^\d*\.?\d+$/. В противном случае вы рискуете либо совпадением таких вещей, как aaa.123.456.bbb, либо отсутствующих совпадений (верьте мне, вы это сделаете. Недостаток поддержки lookbehind в JavaScript гарантирует, что можно будет разорвать любой шаблон, о котором я могу думать).

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

/(\b\d+|\B\.)?\d*\b/g

Это должно быть сделано. Он будет блокировать такие вещи, как aaa123.456bbb, но он позволит 123, 456 или 123.456. Это позволит aaa.123.456.bbb, но, как я уже сказал, вам понадобятся два шага, если вы хотите всесторонне справиться с этим.

Изменить 2: Ваш прецедент

Если вы хотите разрешить пробелы в начале, отрицательные/положительные метки и слова в конце, это на самом деле довольно строгие правила. Это хорошо. Вы можете просто добавить их к простейшему шаблону выше:

/^\s*[-+]?\d*\.?\d+[a-z_\s]*$/i

Разрешение тысяч групп усложняет ситуацию, и я предлагаю вам взглянуть на ответ, с которым я связан. Здесь результирующий шаблон:

/^\s*[-+]?(\d+|\d{1,3}(,\d{3})*)?(\.\d+)?\b(\s[a-z_\s]*)?$/i

\b гарантирует, что числовая часть заканчивается цифрой, а за ней следует как минимум одно пробел.

Ответ 4

Может быть, это помогает (дать вам общую идею):

(?:((?(digits).^|[A-Za-z]+)|(?<digits>\d+))){1,2}

Этот шаблон соответствует символам, цифрам или цифрам следующих символов, но не символы, следующие за цифрами. Шаблон соответствует aa, aa11 и 11, но не 11aa, aa11aa или пустой строке. Не удивляйтесь ". ^", Что означает "символ, следующий за пуском строки", он предназначен для предотвращения любого совпадения вообще.

Обратите внимание, что это не работает со всеми вариантами регулярного выражения, ваша версия регулярного выражения должна поддерживать (?(named group)true|false).