Я не могу понять, как построить регулярное выражение для значений примера:
123,456,789
-12,34
1234
-8
Не могли бы вы мне помочь?
Я не могу понять, как построить регулярное выражение для значений примера:
123,456,789
-12,34
1234
-8
Не могли бы вы мне помочь?
Если вы хотите разрешить только цифры и запятые, ^[-,0-9]+$
является вашим регулярным выражением. Если вы также хотите разрешить пробелы, используйте ^[-,0-9 ]+$
.
Однако, если вы хотите разрешить правильные номера, лучше пойдите с чем-то вроде этого:
^([-+] ?)?[0-9]+(,[0-9]+)?$
или просто используйте парсер .net number (для различных NumberStyles, см. MSDN):
try {
double.Parse(yourString, NumberStyle.Number);
}
catch(FormatException ex) {
/* Number is not in an accepted format */
}
У меня есть простой вопрос для вашего "простого" вопроса: что именно вы подразумеваете под "числом"?
−0
число?√−1
?⅝
или ⅔
число?186,282.42±0.02
мили/секунда одного числа - или это два или три из них?6.02e23
числом?3.141_592_653_589
число? Как насчет π
, или ℯ
? И −2π⁻³ ͥ
?0.083̄
?128.0.0.1
?⚄
? Как насчет ⚂⚃
?10,5 mm
один номер в нем - или у него есть два?∛8³
- или это три из них?ↀↀⅮⅭⅭⅬⅫ AUC
представляет, 2762 или 2009?४५६७
и ৭৮৯৮
?0377
, 0xDEADBEEF
и 0b111101101
?Inf
? Является NaN
?④②
? Что насчет ⓰
?㊅
?ℵ₀
и ℵ₁
? Или ℝ
, ℚ
и ℂ
?Также вы знакомы с этими шаблонами? Можете ли вы объяснить плюсы и минусы каждого?
/\D/
/^\d+$/
/^\p{Nd}+$/
/^\pN+$/
/^\p{Numeric_Value:10}$/
/^\P{Numeric_Value:NaN}+$/
/^-?\d+$/
/^[+-]?\d+$/
/^-?\d+\.?\d*$/
/^-?(?:\d+(?:\.\d*)?|\.\d+)$/
/^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/
/^((\d)(?(?=(\d))|$)(?(?{ord$3==1+ord$2})(?1)|$))$/
/^(?:(?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2}))$/
/^(?:(?:[0-9a-fA-F]{1,2}):(?:[0-9a-fA-F]{1,2}):(?:[0-9a-fA-F]{1,2}):(?:[0-9a-fA-F]{1,2}):(?:[0-9a-fA-F]{1,2}):(?:[0-9a-fA-F]{1,2}))$/
/^(?:(?:[+-]?)(?:[0123456789]+))$/
/(([+-]?)([0123456789]{1,3}(?:,?[0123456789]{3})*))/
/^(?:(?:[+-]?)(?:[0123456789]{1,3}(?:,?[0123456789]{3})*))$/
/^(?:(?i)(?:[+-]?)(?:(?=[0123456789]|[.])(?:[0123456789]*)(?:(?:[.])(?:[0123456789]{0,}))?)(?:(?:[E])(?:(?:[+-]?)(?:[0123456789]+))|))$/
/^(?:(?i)(?:[+-]?)(?:(?=[01]|[.])(?:[01]{1,3}(?:(?:[,])[01]{3})*)(?:(?:[.])(?:[01]{0,}))?)(?:(?:[E])(?:(?:[+-]?)(?:[01]+))|))$/
/^(?:(?i)(?:[+-]?)(?:(?=[0123456789ABCDEF]|[.])(?:[0123456789ABCDEF]{1,3}(?:(?:[,])[0123456789ABCDEF]{3})*)(?:(?:[.])(?:[0123456789ABCDEF]{0,}))?)(?:(?:[G])(?:(?:[+-]?)(?:[0123456789ABCDEF]+))|))$/
/((?i)([+-]?)((?=[0123456789]|[.])([0123456789]{1,3}(?:(?:[_,]?)[0123456789]{3})*)(?:([.])([0123456789]{0,}))?)(?:([E])(([+-]?)([0123456789]+))|))/
Я подозреваю, что некоторые из приведенных выше шаблонов могут удовлетворить ваши потребности. Но я не могу сказать вам, кто из них или кто-то, или, если никто не дает вам другого, потому что вы не сказали, что вы подразумеваете под "номером".
Как вы видите, существует число огромное число числовых возможностей: на самом деле, вероятно, их стоит. ☺
Каждое пронумерованное объяснение, приведенное ниже, описывает шаблон соответствующего пронумерованного шаблона, указанный выше.
\p{Nd}
, \p{Decimal_Number}
или \p{General_Category=Decimal_Number}
. Это поворот на самом деле является лишь отражением тех кодовых пунктов, числовой тип которых - десятичный, доступный как \p{Numeric_Type=Decimal}
.\w
и \w
, \d
и \d
, \s
и \s
, и \b
или \b
в соответствующее свойство Юникода. Это означает, что вы не должны использовать ни один из этих восьми односимвольных экранов для любых данных Unicode в Java, потому что они работают только на ASCII, хотя Java всегда использует символы Unicode внутри.\pN
, \p{Number}
или \p{General_Category=Number}
. К ним относятся \p{Nl}
или \p{Letter_Number}
для таких вещей, как римские цифры и \p{No}
или \p{Other_Number}
для индексированных и индексированных чисел, дробей и числа, к которым они привязаны, - например, счетные стержни.Ⅹ
римская цифра десять, и ⑩
, ⑽
, ⒑
, ⓾
, ❿
, ➉
и ➓
.\1
, предоставляя ее как $1
после успешного совпадения.Шаблоны номер 1,2,7-11 относятся к предыдущему воплощению списка часто задаваемых вопросов Perl в вопросе "Как проверить ввод?". Этот раздел был заменен предложением использовать модуль Regexp::Common, написанный Abigail и Дамиан Конвей. Оригинальные шаблоны все еще можно найти в Рецептуре 2.1 Perl Cookbook, "Проверка правильности номера строки", решения которой могут быть найденных для головокружительного числа различных языков, включая ada, common lisp, groovy, guile, haskell, java, merd, ocaml, php, pike, python, rexx, ruby и tcl в проект PLEAC.
Образец 12 можно было бы более разборчиво переписать
m{
^
(
( \d )
(?(?= ( \d ) ) | $ )
(?(?{ ord $3 == 1 + ord $2 }) (?1) | $ )
)
$
}x
Он использует рекурсию regex, которая встречается во многих моделях шаблонов, включая Perl и все языки, созданные на основе PCRE. Но он также использует встроенную идентификацию кода как тест ее второго условного шаблона; Насколько мне известно, выноски кода доступны только в Perl и PCRE.
Шаблоны 13-21 были получены из вышеупомянутого модуля Regexp:: Common. Обратите внимание, что для краткости все они написаны без пробелов и комментариев, которые вы обязательно захотите в производственном коде. Вот как это выглядит в режиме /x
:
$real_rx = qr{ ( # start $1 to hold entire pattern
( [+-]? ) # optional leading sign, captured into $2
( # start $3
(?= # look ahead for what next char *will* be
[0123456789] # EITHER: an ASCII digit
| [.] # OR ELSE: a dot
) # end look ahead
( # start $4
[0123456789]{1,3} # 1-3 ASCII digits to start the number
(?: # then optionally followed by
(?: [_,]? ) # an optional grouping separator of comma or underscore
[0123456789]{3} # followed by exactly three ASCII digits
) * # repeated any number of times
) # end $4
(?: # begin optional cluster
( [.] ) # required literal dot in $5
( [0123456789]{0,} ) # then optional ASCII digits in $6
) ? # end optional cluster
) # end $3
(?: # begin cluster group
( [E] ) # base-10 exponent into $7
( # exponent number into $8
( [+-] ? ) # optional sign for exponent into $9
( [0123456789] + ) # one or more ASCII digits into $10
) # end $8
| # or else nothing at all
) # end cluster group
) }xi; # end $1 and whole pattern, enabling /x and /i modes
С точки зрения программного обеспечения все еще есть несколько проблем со стилем, используемым в версии режима /x
, приведенным выше. Во-первых, существует много повторений кода, где вы видите тот же [0123456789]
; что произойдет, если одна из этих последовательностей случайно выйдет из цифры? Во-вторых, вы полагаетесь на позиционные параметры, которые вы должны учитывать. Это означает, что вы можете написать что-то вроде:
(
$real_number, # $1
$real_number_sign, # $2
$pre_exponent_part, # $3
$pre_decimal_point, # $4
$decimal_point, # $5
$post_decimal_point, # $6
$exponent_indicator, # $7
$exponent_number, # $8
$exponent_sign, # $9
$exponent_digits, # $10
) = ($string =~ /$real_rx/);
который откровенно отвратительный! Легко получить нумерацию неправильно, трудно вспомнить, какие символические имена отправляются туда, и утомительно писать, особенно если вам не нужны все эти штуки. Переписывая это, чтобы использовать именованные группы вместо просто пронумерованных. Опять же, я использую синтаксис Perl для переменных, но содержимое шаблона должно работать везде, где поддерживаются именованные группы.
use 5.010; # Perl got named patterns in 5.10
$real_rx = qr{
(?<real_number>
# optional leading sign
(?<real_number_sign> [+-]? )
(?<pre_exponent_part>
(?= # look ahead for what next char *will* be
[0123456789] # EITHER: an ASCII digit
| [.] # OR ELSE: a dot
) # end look ahead
(?<pre_decimal_point>
[0123456789]{1,3} # 1-3 ASCII digits to start the number
(?: # then optionally followed by
(?: [_,]? ) # an optional grouping separator of comma or underscore
[0123456789]{3} # followed by exactly three ASCII digits
) * # repeated any number of times
) # end <pre_decimal_part>
(?: # begin optional anon cluster
(?<decimal_point> [.] ) # required literal dot
(?<post_decimal_point>
[0123456789]{0,} )
) ? # end optional anon cluster
) # end <pre_exponent_part>
# begin anon cluster group:
(?:
(?<exponent_indicator> [E] ) # base-10 exponent
(?<exponent_number> # exponent number
(?<exponent_sign> [+-] ? )
(?<exponent_digits> [0123456789] + )
) # end <exponent_number>
| # or else nothing at all
) # end anon cluster group
) # end <real_number>
}xi;
Теперь названы абстракции, что помогает. Вы можете вытащить группы по имени, и вам нужны только те, о которых вы заботитесь. Например:
if ($string =~ /$real_rx/) {
($pre_exponent, $exponent_number) =
@+{ qw< pre_exponent exponent_number > };
}
Это еще одна вещь, чтобы сделать этот шаблон, чтобы сделать его еще более удобным. Проблема в том, что theres все еще слишком много повторений, что означает, что его слишком легко изменить в одном месте, но не в другом. Если вы делаете анализ McCabe, вы бы сказали, что его метрика сложности слишком высока. Большинство из нас просто сказали, что это слишком отступы. Это затрудняет работу. Чтобы исправить все эти вещи, нам нужен "грамматический шаблон", один с блоком определения для создания именованных абстракций, который затем мы будем рассматривать как вызов подпрограммы позже в матче.
use 5.010; # Perl first got regex subs in v5.10
$real__rx = qr{
^ # anchor to front
(?&real_number) # call &real_number regex sub
$ # either at end or before final newline
##################################################
# the rest is definition only; think of ##
# each named buffer as declaring a subroutine ##
# by that name ##
##################################################
(?(DEFINE)
(?<real_number>
(?&mantissa)
(?&abscissa) ?
)
(?<abscissa>
(?&exponent_indicator)
(?&exponent)
)
(?<exponent>
(&?sign) ?
(?&a_digit) +
)
(?<mantissa>
# expecting either of these....
(?= (?&a_digit)
| (?&point)
)
(?&a_digit) {1,3}
(?: (?&digit_separator) ?
(?&a_digit) {3}
) *
(?: (?&point)
(?&a_digit) *
) ?
)
(?<point> [.] )
(?<sign> [+-] )
(?<digit_separator> [_,] )
(?<exponent_indicator> [Ee] )
(?<a_digit> [0-9] )
) # end DEFINE block
}x;
Посмотрите, как безумно лучше грамматический шаблон, чем исходный штриховой шаблон? Его также намного легче получить синтаксис вправо: я набрал это без одной синтаксической ошибки регулярного выражения, которая необходима для исправления. (Хорошо, я тоже набрал все остальные без каких-либо синтаксических ошибок, но я делал это некоторое время.:)
Грамматические модели выглядят скорее как BNF, чем уродливые старые регулярные выражения, которые люди ненавидят. Их гораздо легче читать, писать и поддерживать. Так что давайте не будем иметь более уродливые шаблоны, ОК?
Попробуйте следующее:
^-?\d{1,3}(,\d{3})*(\.\d\d)?$|^\.\d\d$
Позволяет:
1
12
.99
12.34
-18.34
12,345.67
999,999,999,999,999.99
Поскольку этот вопрос был вновь открыт четыре года спустя, я хотел бы предложить другое занятие. Поскольку кто-то тратит много времени на работу с регулярным выражением, мой взгляд таков:
а. Если возможно, не используйте регулярное выражение для проверки номеров
Если это вообще возможно, используйте свой язык. Могут быть функции, которые помогут вам определить, является ли значение, содержащееся в строке, допустимым числом. Если вы принимаете различные форматы (запятые и т.д.), У вас может не быть выбора.
В. Не пишите регулярное выражение для проверки диапазона номеров
С. Проведите разумную энергию Regex: используйте Tools
Для инструментов вы можете использовать:
RegexMagic
(не бесплатный) гуру regex Jan Goyvaerts. Это его новый продукт regex, и, как я помню, у него есть большой выбор опций для генерации чисел в заданном диапазоне, среди других функций.|
Д. Упражнение: построение регулярного выражения для спецификаций в вопросе
Эти спецификации довольно широкие... но не обязательно неопределенные. Давайте снова посмотрим на образцы:
123,456,789
-12,34
1234
-8
Как связаны первые два значения? Во-первых, запятая соответствует группам из трех. Во втором случае он, вероятно, соответствует десятичной точке в формате номера в формате континентального европейского стиля. Это не значит, что мы должны допускать цифры везде, как в 1,2,3,44
. Точно так же мы не должны быть ограничительными. Например, регулярное выражение в принятом ответе не будет соответствовать одному из требований, 123,456,789
(см. demo).
Как мы создаем наше регулярное выражение для соответствия спецификациям?
^
и $
, чтобы избежать подматричек-?
(?:this|that)
:[1-9][0-9]*(?:,[0-9]+)?
[1-9][0-9]{1,2}(?:,[0-9]{3})+
Полное регулярное выражение:
^-?(?:[1-9][0-9]*(?:,[0-9]+)?|[1-9][0-9]{1,2}(?:,[0-9]{3})+)$
Смотрите демо.
Это регулярное выражение не позволяет номера в европейском стиле, начиная с 0
, например 0,12
. Это особенность, а не ошибка. Чтобы соответствовать этим, небольшая настройка сделает:
^-?(?:(?:0|[1-9][0-9]*)(?:,[0-9]+)?|[1-9][0-9]{1,2}(?:,[0-9]{3})+)$
Смотрите демо.
Попробуйте следующее:
^-?[\d\,]+$
Это позволит использовать необязательный -
в качестве первого символа, а затем любую комбинацию запятых и цифр.
^-? # start of line, optional -
(\d+ # any number of digits
|(\d{1,3}(,\d{3})*)) # or digits followed by , and three digits
((,|\.)\d+)? # optional comma or period decimal point and more digits
$ # end of line
^[-+]?(\d{1,3})(,?(?1))*$
Итак, что это?!
^
знаменует начало строки[-+]?
позволяет минус или плюс сразу после начала строки(\d{1,3})
соответствует одной и нескольким ({1,3}
) цифрам (\d
- обычно [0-9]
) в строке и группирует их (скобки (...)
строит группу) в качестве первой группы(,?(?1))*
ok... пусть это сломается
(...)
строит другую группу (не так важно),?
соответствует запятой (если существует) сразу после первой последовательности цифр(?1)
снова соответствует шаблону первой группы (помните (\d{1,3})
); в словах: в этот момент выражение соответствует знаку (плюс/минус/нет), за которым следует последовательность цифр, за которыми следует запятая, за которой следует еще одна последовательность цифр.(,?(?1))*
, *
как можно чаще повторяет вторую часть (запятую и последовательность)$
окончательно совпадает с концом строкиПреимущество таких выражений состоит в том, чтобы избежать повторения одного и того же шаблона в вашем выражении снова и снова... ну, недостатком иногда является сложность: -/
В java вы можете использовать java.util.Scanner
с помощью метода useLocale
Scanner myScanner = new Scanner(input).useLocale( myLocale)
isADouble = myScanner.hasNextDouble()
Для примеров:
^(-)?([,0-9])+$
Он должен работать. Внедрите его в зависимости от того, какой язык вам нужен.
Попробуйте следующее:
boxValue = boxValue.replace(/[^0-9\.\,]/g, "");
Этот RegEx будет соответствовать только цифрам, точкам и запятым.