Регулярное выражение для чисел с плавающей запятой

У меня есть задача сопоставить числа с плавающей запятой. Я написал для него следующее регулярное выражение:

[-+]?[0-9]*\.?[0-9]* 

Но это показывает ошибку:

 Invalid escape sequence (valid ones are \b \t \n \f \r \" \' \\ ) 

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

TL; DR

Используйте [.] Вместо \. и [0-9] вместо \d чтобы избежать проблем с выпуском на некоторых языках (например, Java).

Один относительно простой шаблон для сопоставления числа с плавающей запятой

 [+-]?([0-9]*[.])?[0-9]+ 

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

  • 123
  • 123.456
  • .456

См. Рабочий пример

Если вы также хотите соответствовать 123. (период без десятичной части), вам потребуется немного более длинное выражение:

 [+-]?([0-9]+([.][0-9]*)?|[.][0-9]+) 

См . Ответ pkeller для более полного объяснения этого шаблона

Если вы хотите включить не десятичные числа, такие как hex и восьмеричные, см. Мой ответ « Как определить, является ли строка числом? ,

Если вы хотите проверить, что ввод – это число (вместо того, чтобы находить номер внутри входа), вы должны окружить шаблон с помощью ^ и $ , например:

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

Нерегулярные регулярные выражения

«Регулярные выражения», реализованные на большинстве современных языков, API, фреймворки, библиотеки и т. Д., Основаны на концепции, разработанной в теории формального языка . Тем не менее, разработчики программного обеспечения добавили много расширений, которые принимают эти реализации далеко за frameworks формального определения. Таким образом, хотя большинство двигателей регулярных выражений похожи друг на друга, на самом деле нет стандарта. По этой причине многое зависит от того, какой язык, API, инфраструктура или библиотека вы используете.

(Кстати, чтобы помочь уменьшить путаницу, многие взяли на себя использование « regex » или « regexp » для описания этих улучшенных языков соответствия. См. « Регулярное выражение для регулярного выражения» на RexEgg.com для получения дополнительной информации.)

Тем не менее, большинство движков регулярных выражений (на самом деле, все они, насколько я знаю) принимают \. , Скорее всего, есть проблема с побегом.

Проблема с побегом

(Благодаря безымянному изначально признав это.)

Некоторые языки имеют встроенную поддержку регулярных выражений, таких как JavaScript . Для тех языков, которые этого не делают, побег может быть проблемой.

Это потому, что вы в основном кодируете язык на одном языке. Например, Java использует \ в качестве escape-символа внутри своих строк, поэтому, если вы хотите разместить буквальный символ обратной косой черты внутри строки, вы должны ее избежать:

 // creates a single character string: "\" String x = "\\"; 

Тем не менее, регулярные выражения также используют символ \ для экранирования, поэтому, если вы хотите совместить буквенный символ \ , вы должны убежать от него для механизма regexe, а затем снова запустить его для Java:

 // Creates a two-character string: "\\" // When used as a regex pattern, will match a single character: "\" String regexPattern = "\\\\"; 

В вашем случае вы, вероятно, не избежали символа обратной косой черты на языке, который вы программируете:

 // will most likely result in an "Illegal escape character" error String wrongPattern = "\."; // will result in the string "\." String correctPattern = "\\."; 

Все это ускользает. Если язык, на котором вы работаете, поддерживает исходные строки , вы должны использовать их для сокращения количества обратных косых черт, но не все языки (в первую очередь: Java). К счастью, есть альтернатива, которая будет работать некоторое время:

 String correctPattern = "[.]"; 

Для двигателя регулярных выражений \. и [.] означает точно то же самое. Обратите внимание, что это не работает в каждом случае, например, newline ( \\n ), открытая квадратная скобка ( \\[ ) и обратная косая черта ( \\\\ или [\\] ).

Примечание о сопоставлении номеров

(Подсказка: это сложнее, чем вы думаете)

Соответствие числа – это одна из тех вещей, которые, по вашему мнению, довольно легко с регулярным выражением, но на самом деле это довольно сложно. Давайте взглянем на ваш подход, по частям:

 [-+]? 

Сопоставьте необязательный - или +

 [0-9]* 

Сопоставьте 0 или более последовательных цифр

 \.? 

Совместите необязательный .

 [0-9]* 

Сопоставьте 0 или более последовательных цифр

Во-первых, мы можем немного очистить это выражение, используя сокращенное число символов для цифр (обратите внимание, что это также подвержено проблеме эвакуации, упомянутой выше):

[0-9] = \d

Я буду использовать \d ниже, но имейте в виду, что это означает то же, что и [0-9] . (Ну, на самом деле, в некоторых системах \d будет соответствовать цифрам из всех скриптов, поэтому будет соответствовать больше, чем [0-9] , но это, вероятно, не важно в вашем случае.)

Теперь, если вы посмотрите на это внимательно, вы поймете, что каждая отдельная часть вашего шаблона является необязательной . Этот шаблон может соответствовать строке длиной 0 строк; строка, состоящая только из + или - ; или, строка, состоящая только из a . , Вероятно, это не то, что вы намеревались.

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

 \d+ 

Теперь мы хотим добавить десятичную часть, но это не так, как вы думаете,

 \d+\.?\d* /* This isn't quite correct. */ 

Это все равно будет соответствовать значениям 123. .. Хуже того, у неё есть злобный оттенок . Период необязателен, что означает, что у вас есть два повторных classа бок о бок ( \d+ и \d* ). Это может быть опасно при неправильном использовании, открывая вашу систему до DoS-атак.

Чтобы исправить это, вместо того, чтобы обрабатывать период как необязательный, мы должны обрабатывать его по мере необходимости (чтобы отделить повторяющиеся classы символов) и вместо этого сделать всю десятичную часть необязательной:

 \d+(\.\d+)? /* Better. But... */ 

Сейчас это выглядит лучше. Нам нужен период между первой последовательностью цифр и второй, но есть фатальный недостаток: мы не можем соответствовать .123 потому что теперь требуется ведущая цифра.

На самом деле это довольно легко исправить. Вместо того, чтобы сделать «десятичную» часть числа опциональной, нам нужно посмотреть на нее как на последовательность символов: 1 или более чисел, которые могут быть префиксными . который может иметь префикс 0 или более номеров:

 (\d*\.)?\d+ 

Теперь мы просто добавляем знак:

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

Конечно, эти косые черты довольно раздражают на Java, поэтому мы можем заменить их в наших символьных classах с длинными формами:

 [+-]?([0-9]*[.])?[0-9]+ 

Соответствие и проверка

Это появилось в комментариях пару раз, поэтому я добавляю добавление к сопоставлению и проверке.

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

Regexes, по своей природе, соответствуют только тексту. Учитывая некоторый вклад, они либо найдут подходящий текст, либо не будут. Однако, «привязывая» выражение к началу и концу ввода с помощью тегов привязки ( ^ и $ ), мы можем гарантировать, что совпадение не будет найдено, если весь вход не соответствует выражению, эффективно используя регулярные выражения для проверки .

Регулярное выражение, описанное выше ( [+-]?([0-9]*[.])?[0-9]+ ), будет соответствовать одному или нескольким номерам в целевой строке. Поэтому, учитывая ввод:

 apple 1.34 pear 7.98 version 1.2.3.4 

Регулярное выражение будет соответствовать 1.34 , 7.98 , 1.2 , .3 и .4 .

Чтобы проверить, что данный вход представляет собой число и ничего, кроме числа, «привязать» выражение к началу и концу ввода, обернув его в tags привязки:

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

Это приведет только к совпадению, если весь ввод является числом с плавающей запятой и не будет соответствовать совпадению, если вход содержит дополнительные символы. Итак, учитывая вход 1.2 , будет найдено совпадение, но при условии, что apple 1.2 pear не будет найдено совпадений.

Обратите внимание, что некоторые двигатели регулярных выражений имеют функцию validate , isMatch или аналогичную функцию, которая по существу делает то, что я описал автоматически, возвращая true если совпадение найдено и false если совпадение не найдено. Также имейте в виду, что некоторые двигатели позволяют вам устанавливать флаги, которые изменяют определение ^ и $ , соответствующие началу / концу строки, а не началу / концу всего ввода. Обычно это не значение по умолчанию, но нужно следить за этими флагами.

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

  • Нет десятичной точки (т. Е. Целочисленное значение)
  • Цифры как до, так и после десятичной точки (например, 0.35 , 22.165 )
  • Цифры до десятичной точки (например, 0. , 1234. )
  • Цифры после десятичной точки (например .0 , .5678 )

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

  • десятичная точка сама по себе
  • подписанная десятичная точка без цифр (например, +. или -. )
  • + или - самостоятельно
  • пустая строка

Сначала это кажется сложным, но одним из способов найти вдохновение является просмотр исходного файла OpenJDK для метода java.lang.Double.valueOf(String) (начало в http://hg.openjdk.java.net/jdk8/jdk8 / jdk , нажмите «просмотреть», перейдите вниз /src/share/classes/java/lang/ и найдите Double Class). Длинное регулярное выражение, которое этот class содержит, содержит различные возможности, которые OP, вероятно, не имел в виду, но игнорируя для простоты его части, которые имеют дело с NaN, бесконечностью, шестнадцатеричной нотацией и показателями и используют \d а не POSIX нотация для одной цифры, я могу уменьшить важные части регулярного выражения для числа с плавающей запятой с подписью без экспоненты:

[+-]?((\d+\.?\d*)|(\.\d+))

Я не думаю, что есть способ избежать построения (...)|(...) не допуская того, что не содержит цифр, или запрещает одну из возможностей, которая не имеет цифр до десятичной точки или без цифр после этого.

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

вам нужно:

 [\-\+]?[0-9]*(\.[0-9]+)? 

Я избежал знака «+» и «-», а также сгруппировал десятичную цифру со следующими цифрами, так как нечто вроде «1». не является допустимым числом.

Изменения позволят вам сопоставлять целые числа и поплавки. например:

 0 +1 -2.0 2.23442 

Это просто: вы использовали Java, и вы должны использовать \\. вместо \. (поиск символа в Java).

Это работало для меня:

 (?P[-+]*\d+\.\d+|[-+]*\d+) 

Вы также можете использовать этот (без именованного параметра):

 ([-+]*\d+\.\d+|[-+]*\d+) 

Используйте некоторые онлайн-тестер для проверки языка (например, regex101)

 [+-]?(([1-9][0-9]*)|(0))([.,][0-9]+)? 

[+-]? – дополнительный указатель

(([1-9][0-9]*)|(0)) – целое число без начального нуля, включая один ноль

([.,][0-9]+)? – необязательная дробная часть

 ^[+]?([0-9]{1,2})*[.,]([0-9]{1,1})?$ 

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

  1. 1.2
  2. 12,3
  3. 1,2
  4. 12,3
 [+/-] [0-9]*.[0-9]+ 

Попробуйте это решение.

для javascript

 const test = new RegExp('^[+]?([0-9]{0,})*[.]?([0-9]{0,2})?$','g'); 

Что будет работать на 1,23 1234,22 0 0,12 12

Вы можете изменить части в {} чтобы получить разные результаты в десятичной и десятичной форме. Это используется в вводах для ввода числа и проверки каждого входа, когда вы вводите только то, что проходит.

  • Преобразование символа в верхний регистр с использованием регулярных выражений (EditPad Pro)
  • Найдите «слово», а не «@»
  • Как (* SKIP) или (* F) работают над регулярным выражением?
  • Регулярное выражение
  • Может ли расширенная реализация регулярных выражений анализировать HTML?
  • Регулярное выражение, которое не содержит определенной строки
  • Регулярное выражение противоположно
  • Regex: соответствие до первого появления символа
  • Regex - Должны ли экраны сбрасываться?
  • Что такое регулярное выражение для MAC-адреса?
  • Какое регулярное выражение никогда не будет соответствовать?
  • Давайте будем гением компьютера.