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


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

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

но он показывает ошибку, говоря:

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

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

9 64

9 ответов:

TL; DR

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

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

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

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

  • 123
  • 123.456
  • .456

посмотреть рабочая пример

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

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

посмотреть pkeller это для более полного объяснения этой картины

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

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

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

нерегулярные Регулярные Выражения

"регулярные выражения", как это реализовано в большинстве современных языков, интерфейсы API, фреймворков, библиотек и т. д. основаны на концепции, разработанной в теория формального языка. Тем не менее, инженеры-программисты добавили много расширения, которые выводят эти реализации далеко за рамки формального определения. Таким образом, хотя большинство механизмов регулярных выражений похожи друг на друга, на самом деле нет стандарта. По этой причине многое зависит от того, какой язык, API, фреймворк или библиотека вы используете.

(кстати, чтобы уменьшить путаницу, многие стали использовать "выражение" или "и " чтобы описать эти улучшенные соответствующие языки. Смотрите является регулярным выражением таким же, как обычный Выражение лица? at 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-длины; строка, состоящая только из + или -; или строка, состоящая только из .. Это, вероятно, не то, что вы намеревались.

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

\d+

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

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

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

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

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

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

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

(\d*\.)?\d+

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

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

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

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

сопоставление и проверка

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

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

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

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

apple 1.34 pear 7.98 version 1.2.3.4

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

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

^[+-]?([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 класс). Длинное регулярное выражение, которое содержит этот класс, обслуживает различные возможности, которые OP, вероятно, не имел в виду, но игнорирует для простоты его части, которые имеют дело с NaN, бесконечностью, шестнадцатеричной нотацией и экспонентами и используют \d вместо обозначения POSIX для одной цифры я могу уменьшить важные части регулярного выражения для числа со знаком с плавающей запятой без экспоненты до:

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

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

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

что нужно:

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

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

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

0
+1
-2.0
2.23442

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

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

(?P<value>[-+]*\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.12 12

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