부동 소수점 수에 대한 정규식
부동 소수점 숫자를 일치시키는 작업이 있습니다. 다음 정규식을 작성했습니다.
[-+]?[0-9]*\.?[0-9]*
그러나 오류를 반환합니다.
Invalid escape sequence (valid ones are \b \t \n \f \r \" \' \\ )
내 지식에 따라, 우리는 .
또한 이스케이프 문자를 사용해야합니다 . 내가 틀린 부분을 수정하십시오.
TL; DR
일부 언어 (예 : Java)에서 이스케이프 문제를 방지 하려면 [.]
대신 \.
및 [0-9]
대신 사용하십시오 \d
.
원래 이것을 인식 한 이름없는 사람 에게 감사합니다 .
부동 소수점 수 를 일치 시키는 비교적 간단한 패턴 은 다음과 같습니다.
[+-]?([0-9]*[.])?[0-9]+
다음과 일치합니다.
123
123.456
.456
참조 작업 예를
또한 일치 시키려면 123.
(소수점이없는 마침표) 약간 더 긴 표현식이 필요합니다.
[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)
이 패턴에 대한 자세한 설명은 pkeller의 답변 을 참조하십시오.
16 진수 및 8 진수와 같은 10 진수가 아닌 숫자를 포함하려면 문자열이 숫자인지 확인하는 방법에 대한 답변을 참조하세요 . .
당신이하려는 경우 확인 입력은 숫자 (대신 입력 내 번호를 찾는) 인 것을, 당신은과 패턴을 포위해야 ^
하고 $
, 그래서 같은 :
^[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)$
불규칙한 정규 표현식
대부분의 최신 언어, API, 프레임 워크, 라이브러리 등에 구현 된 "정규 표현식"은 공식 언어 이론 에서 개발 된 개념을 기반으로합니다 . 그러나 소프트웨어 엔지니어는 이러한 구현을 공식적인 정의를 훨씬 뛰어 넘는 많은 확장 기능을 추가했습니다. 따라서 대부분의 정규식 엔진은 서로 유사하지만 실제로는 표준이 없습니다. 따라서 사용중인 언어, API, 프레임 워크 또는 라이브러리에 따라 많은 것이 달라집니다.
(부수적으로 혼동을 줄이기 위해 많은 사람들이 " regex "또는 " regexp " 를 사용하여 이러한 향상된 일치 언어를 설명했습니다. 자세한 내용 은 RexEgg.com에서 정규 표현식과 정규 표현식이 동일합니까? 를 참조하십시오.)
즉, 대부분의 정규식 엔진 (실제로 내가 아는 한 모두)은 \.
. 대부분의 경우 이스케이프에 문제가 있습니다.
탈출 문제
일부 언어에는 JavaScript와 같은 정규식에 대한 기본 지원이 있습니다. 그렇지 않은 언어의 경우 이스케이프가 문제가 될 수 있습니다.
이것은 기본적으로 언어 내의 언어로 코딩하기 때문입니다. 예를 들어 Java는 \
문자열 내에서 이스케이프 문자로 사용 하므로 문자열 내에 리터럴 백 슬래시 문자를 배치하려면 이스케이프해야합니다.
// 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 = "[.]";
정규식 엔진, \.
그리고 [.]
정확히 같은 일을 의미한다. 줄 바꿈 ( \\n
), 여는 대괄호 ( \\[
) 및 백 슬래시 ( \\\\
또는 [\\]
) 와 같이 모든 경우에 작동하는 것은 아닙니다 .
일치하는 숫자에 대한 참고 사항
(힌트 : 생각보다 어렵습니다)
숫자를 일치시키는 것은 정규식으로 매우 쉽다고 생각하는 것 중 하나이지만 실제로는 매우 까다 롭습니다. 귀하의 접근 방식을 하나씩 살펴 보겠습니다.
[-+]?
선택적 -
또는 일치+
[0-9]*
0 개 이상의 연속 숫자와 일치
\.?
선택 사항 일치 .
[0-9]*
0 개 이상의 연속 숫자와 일치
먼저 숫자에 대한 문자 클래스 속기 를 사용하여이 표현식을 약간 정리할 수 있습니다 (위에서 언급 한 이스케이프 문제의 영향을 받기도합니다).
[0-9]
= \d
\d
아래에서 사용하려고하는데 [0-9]
. (실제로 일부 엔진 \d
에서는 모든 스크립트의 숫자와 일치하므로 원하는 것보다 더 많이 일치 [0-9]
하지만 귀하의 경우에는 그다지 중요하지 않습니다.)
Now, if you look at this carefully, you'll realize that every single part of your pattern is optional. This pattern can match a 0-length string; a string composed only of +
or -
; or, a string composed only of a .
. This is probably not what you've intended.
To fix this, it's helpful to start by "anchoring" your regex with the bare-minimum required string, probably a single digit:
\d+
Now we want to add the decimal part, but it doesn't go where you think it might:
\d+\.?\d* /* This isn't quite correct. */
This will still match values like 123.
. Worse, it's got a tinge of evil about it. The period is optional, meaning that you've got two repeated classes side-by-side (\d+
and \d*
). This can actually be dangerous if used in just the wrong way, opening your system up to DoS attacks.
To fix this, rather than treating the period as optional, we need to treat it as required (to separate the repeated character classes) and instead make the entire decimal portion optional:
\d+(\.\d+)? /* Better. But... */
This is looking better now. We require a period between the first sequence of digits and the second, but there's a fatal flaw: we can't match .123
because a leading digit is now required.
This is actually pretty easy to fix. Instead of making the "decimal" portion of the number optional, we need to look at it as a sequence of characters: 1 or more numbers that may be prefixed by a .
that may be prefixed by 0 or more numbers:
(\d*\.)?\d+
Now we just add the sign:
[+-]?(\d*\.)?\d+
Of course, those slashes are pretty annoying in Java, so we can substitute in our long-form character classes:
[+-]?([0-9]*[.])?[0-9]+
Matching versus Validating
This has come up in the comments a couple times, so I'm adding an addendum on matching versus validating.
The goal of matching is to find some content within the input (the "needle in a haystack"). The goal of validating is to ensure that the input is in an expected format.
Regexes, by their nature, only match text. Given some input, they will either find some matching text or they will not. However, by "snapping" an expression to the beginning and ending of the input with anchor tags (^
and $
), we can ensure that no match is found unless the entire input matches the expression, effectively using regexes to validate.
The regex described above ([+-]?([0-9]*[.])?[0-9]+
) will match one or more numbers within a target string. So given the input:
apple 1.34 pear 7.98 version 1.2.3.4
The regex will match 1.34
, 7.98
, 1.2
, .3
and .4
.
To validate that a given input is a number and nothing but a number, "snap" the expression to the start and end of the input by wrapping it in anchor tags:
^[+-]?([0-9]*[.])?[0-9]+$
This will only find a match if the entire input is a floating point number, and will not find a match if the input contains additional characters. So, given the input 1.2
, a match will be found, but given apple 1.2 pear
no matches will be found.
Note that some regex engines have a validate
, isMatch
or similar function, which essentially does what I've described automatically, returning true
if a match is found and false
if no match is found. Also keep in mind that some engines allow you to set flags which change the definition of ^
and $
, matching the beginning/end of a line rather than the beginning/end of the entire input. This is typically not the default, but be on the lookout for these flags.
I don't think that any of the answers on this page at the time of writing are correct (also many other suggestions elsewhere on SO are wrong too). The complication is that you have to match all of the following possibilities:
- No decimal point (i.e. an integer value)
- Digits both before and after the decimal point (e.g.
0.35
,22.165
) - Digits before the decimal point only (e.g.
0.
,1234.
) - Digits after the decimal point only (e.g.
.0
,.5678
)
At the same time, you must ensure that there is at least one digit somewhere, i.e. the following are not allowed:
- a decimal point on its own
- a signed decimal point with no digits (i.e.
+.
or-.
) +
or-
on their own- an empty string
This seems tricky at first, but one way of finding inspiration is to look at the OpenJDK source for the java.lang.Double.valueOf(String)
method (start at http://hg.openjdk.java.net/jdk8/jdk8/jdk, click "browse", navigate down /src/share/classes/java/lang/
and find the Double
class). The long regex that this class contains caters for various possibilities that the OP probably didn't have in mind, but ignoring for simplicity the parts of it that deal with NaN, infinity, Hexadecimal notation and exponents, and using \d
rather than the POSIX notation for a single digit, I can reduce the important parts of the regex for a signed floating point number with no exponent to:
[+-]?((\d+\.?\d*)|(\.\d+))
I don't think that there is a way of avoiding the (...)|(...)
construction without allowing something that contains no digits, or forbidding one of the possibilities that has no digits before the decimal point or no digits after it.
Obviously in practice you will need to cater for trailing or preceding whitespace, either in the regex itself or in the code that uses it.
what you need is:
[\-\+]?[0-9]*(\.[0-9]+)?
I escaped the "+" and "-" sign and also grouped the decimal with its following digits since something like "1." is not a valid number.
The changes will allow you to match integers and floats. for example:
0
+1
-2.0
2.23442
This is simple: you have used Java and you ought to use \\.
instead of \.
(search for character escaping in Java).
I want to match what most languages consider valid numbers (integer and floats):
'5' / '-5'
'1.0' / '1.' / '.1' / '-1.' / '-.1'
'0.45326e+04', '666999e-05', '0.2e-3', '-33.e-1'
Notes:
preceding sign of number ('-' or '+') is optional
'-1.' and '-.1' are valid but '.' and '-.' are invalid
'.1e3' is valid, but '.e3' and 'e3' are invalid
In order to support both '1.' and '.1' we need an OR operator ('|') in order to make sure we exclude '.' from matching.
[+-]?
+/- sing is optional since ?
means 0 or 1 matches
(
since we have 2 sub expressions we need to put them in parenthesis
\d+([.]\d*)?(e[+-]?\d+)?
This is for numbers starting with a digit
|
separates sub expressions
[.]\d+(e[+-]?\d+)?
this is for numbers starting with '.'
)
end of expressions
- For numbers starting with '.'
[.]
first character is dot (inside brackets or else it is a wildcard character)
\d+
one or more digits
(e[+-]?\d+)?
this is an optional (0 or 1 matches due to ending '?') scientific notation
- For numbers starting with a digit
\d+
one or more digits
([.]\d*)?
optionally we can have a dot character an zero or more digits after it
(e[+-]?\d+)?
this is an optional scientific notation
- Scientific notation
e
literal that specifies exponent
[+-]?
optional exponent sign
\d+
one or more digits
All of those combined:
[+-]?(\d+([.]\d*)?(e[+-]?\d+)?|[.]\d+(e[+-]?\d+)?)
This one worked for me:
(?P<value>[-+]*\d+\.\d+|[-+]*\d+)
You can also use this one (without named parameter):
([-+]*\d+\.\d+|[-+]*\d+)
Use some online regex tester to test it (e.g. regex101 )
[+-]?(([1-9][0-9]*)|(0))([.,][0-9]+)?
[+-]?
- optional leading sign
(([1-9][0-9]*)|(0))
- integer without leading zero, including single zero
([.,][0-9]+)?
- optional fractional part
^[+]?([0-9]{1,2})*[.,]([0-9]{1,1})?$
This will match:
- 1.2
- 12.3
- 1,2
- 12,3
In C++ using the regex library
The answer would go about like this:
[0-9]?([0-9]*[.])?[0-9]+
Notice that I don't take the sign symbol, if you wanted it with the sign symbol it would go about this:
[+-]?([0-9]*[.])?[0-9]+
This also separates a regular number or a decimal number.
[+/-] [0-9]*.[0-9]+
Try this solution.
for javascript
const test = new RegExp('^[+]?([0-9]{0,})*[.]?([0-9]{0,2})?$','g');
Which would work for 1.23 1234.22 0 0.12 12
You can change the parts in the {}
to get different results in decimal length and front of the decimal as well. This is used in inputs for entering in number and checking every input as you type only allowing what passes.
참고URL : https://stackoverflow.com/questions/12643009/regular-expression-for-floating-point-numbers
'developer tip' 카테고리의 다른 글
부울에 대한 문자열 "true"및 "false" (0) | 2020.09.23 |
---|---|
rawQuery (query, selectionArgs) (0) | 2020.09.23 |
파일 이름에 대한 빠른 검색 Android Studio (0) | 2020.09.23 |
C #에서 Base64 URL 안전 인코딩을 달성하는 방법은 무엇입니까? (0) | 2020.09.23 |
Spark Scala에서 DataFrame의 열 이름 이름 바꾸기 (0) | 2020.09.23 |