부동 소수점 수에 대한 정규식


115

부동 소수점 숫자를 일치시키는 작업이 있습니다. 다음 정규식을 작성했습니다.

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

그러나 오류를 반환합니다.

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

내 지식에 따라, 우리는 .또한 이스케이프 문자를 사용해야합니다 . 내가 틀린 부분을 수정하십시오.


10
이 정규식은 어떤 언어로 사용됩니까?
CaffGeek

3
@JDB-왜 숫자 / 부동 정규식에 대해 100 점을 주나요? 표준은 항상 그래 왔고 (?:\d+(?:\.\d*)?|\.\d+)그래서 광고 무한대로 게시되었습니다 ...


1
[-+]?([0-9]*[.])?[0-9]+([eE][-+]?\d+)?당신은 지수도 표기, E, G를 잡을하려는 경우 3.023e-23
wcochran

Java 또는 C ++와 같은 일부 언어에서는 백 슬래시를 이스케이프해야합니다. 따라서 정규식 "\."을 얻으려면 문자열 "\\."를 사용합니다. 파이썬은 원시 문자열을 사용하여이 문제를 해결합니다.
HackerBoss

답변:


258

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 \ 이스케이프 에도 문자를 사용 하므로 리터럴 \문자 와 일치 시키려면 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]하지만 귀하의 경우에는 그다지 중요하지 않을 것입니다.)

이제 이것을주의 깊게 살펴보면 패턴의 모든 부분이 선택 사항 이라는 것을 알 수 있습니다 . 이 패턴은 길이가 0 인 문자열과 일치 할 수 있습니다. +또는 로만 구성된 문자열 -; 또는 .. 이것은 아마도 당신이 의도 한 것이 아닐 것입니다.

이 문제를 해결하려면 최소한의 필수 문자열 (아마도 한 자리 숫자 일 수 있음)로 정규식을 "고정"하여 시작하는 것이 좋습니다.

\d+

이제 소수점 부분을 추가하고 싶지만 여러분이 생각하는 곳에 가지 않습니다.

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

이것은 여전히 123.. 더 나쁜 것은 그것에 대해 사악한 색조가 있습니다. 마침표는 선택 사항입니다. 즉, 두 개의 반복되는 클래스가 나란히 표시됩니다 ( \d+\d*). 잘못된 방식으로 사용하면 시스템이 DoS 공격에 노출 될 경우 실제로 위험 할 수 있습니다.

이 문제를 해결하려면 마침표를 선택 사항으로 처리하는 대신 필수로 처리하고 (반복 문자 클래스를 구분하기 위해) 대신 전체 소수 부분을 선택 사항으로 만들어야합니다.

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

이것은 이제 더 좋아 보입니다. 첫 번째 숫자 시퀀스와 두 번째 숫자 사이에 마침표가 필요하지만 치명적인 결함 .123이 있습니다. 이제 선행 숫자가 필요하기 때문에 일치 할 수 없습니다 .

이것은 실제로 수정하기가 매우 쉽습니다. 숫자의 "십진수"부분을 선택적으로 만드는 대신 문자 시퀀스로 살펴볼 필요 .가 있습니다. 0 개 이상의 숫자가 접두사로 붙을 수있는 a 가 접두사로 붙을 수있는 1 개 이상의 숫자 :

(\d*\.)?\d+

이제 기호를 추가합니다.

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

물론 이러한 슬래시는 자바에서 매우 성가 시므로 긴 형식의 문자 클래스로 대체 할 수 있습니다.

[+-]?([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. 또한 일부 엔진에서는 전체 입력의 시작 / 끝이 아닌 줄의 시작 / 끝과 일치하는 ^및 의 정의를 변경하는 플래그를 설정할 수 있습니다 $. 이것은 일반적으로 기본값은 아니지만 이러한 플래그를 확인해야합니다.


2
JDB, 감사합니다. 아직 주변에 있기를 바랍니다! 나는 앞으로 귀하의 게시물을 읽고 있습니다 :) 귀하의 답변은 확실히 0.24 및 2.2를 처리하고 4.2.44를 올바르게 허용하지 않습니다. 모두 regex101.com으로 테스트 되었지만 123을 허용하지 않습니다. 이다!). 식을 [-+]? (\ d * [.])? \ d * (+ 대신 * 끝에주의)로 변경하여이 문제를 해결할 수 있지만. (두 번째 예) 허용됩니다. 어쨌든 내 케이크도 먹고 먹으려 고?
Dave

2
@ 데이브는 -\d+(\.\d*)?|\.\d+
JDB은 여전히 모니카 기억

/[-+]?(\d*[.])?\d+/.test("1.bc") // returns true
yeouuu

1
@yeouuu 네, 1.일치 하기 때문에 . 추가 ^$시작과 당신은 단지 전체 입력과 일치하면 일치 할 경우 정규 표현식의 끝.
JDB은 여전히 모니카 기억

5
float는 지수를 갖거나 NaN / Inf가 될 수 있으므로 이것을 사용합니다 : [-+]?(([0-9]*[.]?[0-9]+([ed][-+]?[0-9]+)?)|(inf)|(nan)), e / d for float / double precision float. 정규식에 배 경우 플래그 잊지 마세요
마르쿠스 Schmassmann

23

글을 쓰는 시점에이 페이지의 답변 중 어느 것도 정확하다고 생각하지 않습니다 (SO의 다른 많은 제안도 잘못되었습니다). 문제는 다음과 같은 가능성을 모두 충족시켜야한다는 것입니다.

  • 소수점 없음 (예 : 정수 값)
  • 소수점 앞뒤의 숫자 (예 : 0.35, 22.165)
  • 소수점 앞의 숫자 만 (예 : 0., 1234.)
  • 소수점 뒤의 숫자 만 (예 : .0, .5678)

동시에 어딘가에 적어도 하나의 숫자가 있는지 확인해야합니다. 즉, 다음은 허용되지 않습니다.

  • 그 자체로 소수점
  • 숫자가없는 부호있는 소수점 (예 : +.또는 -.)
  • +또는 -스스로
  • 빈 문자열

처음에는 까다로워 보이지만 영감을 얻는 한 가지 방법은 java.lang.Double.valueOf(String)메서드 에 대한 OpenJDK 소스를 살펴 보는 것입니다 ( http://hg.openjdk.java.net/jdk8/jdk8/jdk 에서 시작하고 "찾아보기"를 클릭하고 아래로 이동) 클래스 /src/share/classes/java/lang/찾기 Double). 이 클래스에 포함 된 긴 정규식은 OP가 염두에 두지 않았을 다양한 가능성을 충족하지만 NaN, 무한대, 16 진수 표기법 및 지수를 처리하는 부분을 단순하게 무시 \d하고 POSIX 표기법 대신 사용 지수가없는 부호있는 부동 소수점 숫자에 대한 정규식의 중요한 부분을 다음과 같이 줄일 수 있습니다.

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

나는 (...)|(...)숫자가없는 것을 허용하지 않고, 또는 소수점 앞에 숫자가 없거나 뒤에 숫자가없는 가능성 중 하나를 금지하지 않고 구성 을 피하는 방법이 없다고 생각 합니다.

분명히 실제로는 정규식 자체 또는이를 사용하는 코드에서 후행 또는 선행 공백을 처리해야합니다.


와 같은 숫자를 일치시키는 요구 사항을 추가하면 123.예 ... 또는 스위치가 유일한 해결책 입니다. 원래 게시물 에 대한 의견 에서 지적했듯이 .
JDB은 여전히 모니카 기억

1
이것과 대부분의 다른 대답은 float가 지수를 가질 수 있음을 무시합니다.
NateS

1
@NateS 맞습니다. "NaN, 무한대, 16 진수 표기법 및 지수를 다루는 부분은 단순하게 무시하고"OP의 질문 범위와 일치하는 것 같기 때문에 작성했습니다. JDK 소스 코드에서 찾은 것을 포함하여 더 완전한 구현이 있습니다.
pkeller 2011

1
[+-]?((?=\.?\d)\d*\.?\d*)교대를 피하기 위해 정규식 을 사용할 수 있습니까 ? 그것은
예견을

1
@ 4esn0k 좋은 정규식! 나는 그것을 가지고 놀았고 작동합니다. 두 가지주의 사항이 있습니다. (1) 모든 정규식 엔진이 너비가 0 인 어설 션을 지원하는 것은 아닙니다 (대부분의 현대식 엔진이 AFAIK를 지원하지만). (2) 미리보기는 다른 이름의 대체 일뿐입니다. 엔진은 여전히 ​​무언가를 시도해야합니다 작동하지 않으면 역 추적합니다. 그럼에도 불구하고 매우 깔끔한 아이디어에 찬성 투표를하십시오.
pkeller

7

필요한 것은 :

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

나는 "+"와 "-"기호를 이스케이프하고 "1"과 같은 것이므로 다음 숫자로 소수를 그룹화했습니다. 유효한 번호가 아닙니다.

변경 사항으로 정수 및 부동 소수점을 일치시킬 수 있습니다. 예를 들면 :

0
+1
-2.0
2.23442

이 표현의 문제는 .1그러한 입력이 보편적으로 옳다고 인식 되더라도 허용되지 않는다는 것입니다.
JDB은 여전히 모니카 기억

이제 숫자가 아닌 길이가 0 인 문자열 -및을 허용 +합니다. Regex는 까다 롭습니다! :)
JDB은 여전히 모니카 기억

또한 이것은 작동하지 않는 OP의 실제 질문에 대한 답변 \.이 아닙니다.
JDB은 여전히 모니카 기억

7

대부분의 언어가 유효한 숫자 (정수 및 부동 소수점)로 간주하는 것과 일치시키고 싶습니다.

  • '5' / '-5'

  • '1.0' / '1.' / '.1' / '-1.' / '-.1'

  • '0.45326e+04', '666999e-05', '0.2e-3', '-33.e-1'

노트:

  • 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

'1'을 모두 지원하기 위해. '.1'을 제외하려면 OR 연산자 ( '|')가 필요합니다. 일치에서.

[+-]?+/- sing은 ?0 또는 1 일치를 의미 하므로 선택 사항입니다.

( 2 개의 하위 표현식이 있으므로 괄호 안에 넣어야합니다.

\d+([.]\d*)?(e[+-]?\d+)? 숫자로 시작하는 숫자 용입니다.

| 하위 표현식을 분리합니다.

[.]\d+(e[+-]?\d+)? '.'로 시작하는 숫자 용입니다.

) 식의 끝

  • '.'로 시작하는 숫자의 경우

[.] 첫 번째 문자는 점 (대괄호 안에 있거나 와일드 카드 문자 임)

\d+ 하나 이상의 숫자

(e[+-]?\d+)? 이것은 선택적 ( '?'로 인해 0 또는 1 개의 일치) 과학적 표기법입니다.

  • 숫자로 시작하는 숫자

\d+ 하나 이상의 숫자

([.]\d*)? 선택적으로 점 문자 뒤에 0 개 이상의 숫자를 지정할 수 있습니다.

(e[+-]?\d+)? 이것은 선택적 과학적 표기법입니다.

  • 과학적 표기법

e 지수를 지정하는 리터럴

[+-]? 선택적 지수 부호

\d+ 하나 이상의 숫자

모두 결합 :

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

또한 수락하려면 E:

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

( 테스트 사례 )


4

이것은 간단합니다. Java를 사용 했으며 (Java에서 문자 이스케이프 검색) \\.대신 사용해야 합니다 \..


아마 맞을 것입니다. 오류 메시지는 정규식 파서 오류가 아닌 프로그래밍 언어 구문 오류처럼 보입니다.
JDB은 여전히 모니카 기억

3

이것은 나를 위해 일했습니다.

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

다음을 사용할 수도 있습니다 (명명 된 매개 변수없이).

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

온라인 정규식 테스터를 사용하여 테스트합니다 (예 : regex101).


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

다음과 일치합니다.

  1. 1.2
  2. 12.3
  3. 1,2
  4. 12,3

이 코드 스 니펫은 환영하며 약간의 도움을 줄 수 있지만 문제를 해결하는 방법이유에 대한 설명포함되어 있으면 크게 개선 될 것 입니다. 지금 질문하는 사람뿐만 아니라 미래에 독자를 위해 질문에 답하고 있다는 것을 기억하십시오! 제발 편집 설명을 추가하고, 제한 및 가정이 적용 무엇의 표시를 제공하는 답변을.
Toby Speight 2017

오 thnks, 나는 이것을 위해 lokking
오전

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

[+-]? -선택적 선행 기호

(([1-9][0-9]*)|(0)) -단일 0을 포함하여 선행 0이없는 정수

([.,][0-9]+)? -선택적 분수 부분


1
더 많은 정보를 제공하십시오-정규 표현식을 모르는 사람들에게는 hyerogliphs입니다. 그들을 아는 사람들에게는 필요하지 않습니다.
peterh-Monica 복원

0

정규식 라이브러리를 사용하는 C ++에서

대답은 다음과 같습니다.

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

내가 기호 기호를 사용하지 않는다는 점에 유의하십시오. 기호 기호와 함께 원하는 경우 다음과 같이됩니다.

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

이것은 또한 일반 숫자 또는 10 진수를 구분합니다.


0

c 표기법에서 float 숫자는 다음과 같은 형태로 나타날 수 있습니다.

  1. 123
  2. 123.
  3. 123.24
  4. .24
  5. 2e-2 = 2 * 10 pow -2 = 2 * 0.1
  6. 4E + 4 = 4 * 10 pow 4 = 4 * 10,000

float 정규 표현식을 만들기 위해 먼저 "int 정규 표현식 변수"를 만듭니다.

(([1-9][0-9]*)|0) will be int

이제 float 정규식의 작은 덩어리를 작성할 것입니다. 해결책은 그 덩어리를 또는 심볼 "|"로 연결하는 것입니다.

청크 :

- (([+-]?{int}) satysfies case 1
- (([+-]?{int})"."[0-9]*)  satysfies cases 2 and 3
- ("."[0-9]*) satysfies case 4
- ([+-]?{int}[eE][+-]?{int}) satysfies cases 5 and 6

최종 솔루션 (작은 청크 연결) :

(([+-]?{int})|(([+-]?{int})"."[0-9]*)|("."[0-9]*)|([+-]?{int}[eE][+-]?{int})


-1

자바 스크립트 용

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

1.23 1234.22 0 0.12 12에서 작동합니다.

의 부분을 변경하여 {}소수점 길이와 소수점 앞부분에서도 다른 결과를 얻을 수 있습니다. 이것은 숫자를 입력하고 입력 할 때 모든 입력을 확인하기위한 입력에 사용되며 통과하는 것만 허용합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.