위도 / 경도 좌표를 일치시키기위한 정규식?


149

위도 / 경도 좌표를 일치시키는 정규식을 만들려고합니다. 배정 밀도 숫자를 일치시키기 위해을 사용 (\-?\d+(\.\d+)?)하고 단일 표현식으로 결합하려고했습니다.

^(\-?\d+(\.\d+)?),\w*(\-?\d+(\.\d+)?)$

나는 이것이 더블, 쉼표, 아마도 약간의 스페이스 및 다른 더블과 일치 할 것으로 예상했지만 작동하지 않는 것 같습니다. 특히 하나 이상의 공간이없는 경우에만 작동합니다. 내가 뭘 잘못 했니?

답변:


117

공백은 \ w가 아니라 \ s입니다.

^(-?\d+(\.\d+)?),\s*(-?\d+(\.\d+)?)$

이것이 작동하는지 확인하십시오


1
쉼표 대신 점을 사용해야했습니다 : /^(\-?\d+(\.\d+)?) hereAdot. endMod \ s * (\-? \ d + (\. \ d +)?) $ /
— kolodi

위도 및 경도에 허용되는 범위 밖의 값을 허용합니다. 예 : 91,181
— Arun Karunagath

이것은 투영 된 공간 참조 시스템의 x / y 좌표에도 적용됩니다.
— DeEgge

218

이것은 올바른 범위에 속하는 위도 및 경도 값과 엄격하게 일치합니다.

^[-+]?([1-8]?\d(\.\d+)?|90(\.0+)?),\s*[-+]?(180(\.0+)?|((1[0-7]\d)|([1-9]?\d))(\.\d+)?)$

성냥

  • +90.0, -127.554334
  • 45, 180
  • -90, -180
  • -90.000, -180.0000
  • +90, +180
  • 47.1231231, 179.99999999

일치하지 않습니다

  • -90., -180.
  • +90.1, -100.111
  • -91, 123.456
  • 045, 180

대단해. 범위 확인 포함에 대한 명성.
— radj

1
첫 번째 일치 예제에 오타가 있다고 생각합니다. RegEx가 3 개의 값과 일치하는지 의심합니다.
— Burkhard

결정된. 그것은 두 개의 별개의 예가되어야했다.
— Iain Fraser

7
쉼표의 양쪽에 공백을 허용하도록 수정했습니다 : ^ [-+]? ([1-8]? \ d (\. \ d +)? | 90 (\. 0 +)?) \ s *, \ s * [-+]? (180 (\. 0 +)? | ((1 [0-7] \ d) | ([1-9]? \ d)) (\. \ d +)?) $
— puddinman13

2
캡처 ?:하지 않은 그룹 구문과 캡처 극성 을 사용하여 캡처 그룹에서 위도를 얻도록 이것을 변경했습니다.(^[-+]?(?:[1-8]?\d(?:\.\d+)?|90(?:\.0+)?)),\s*([-+]?(?:180(?:\.0+)?|(?:(?:1[0-7]\d)|(?:[1-9]?\d))(?:\.\d+)?))$
— narthur157

109

다음 중 하나를 사용하고 있습니다 (10 진수 6 자리).

위도

^(\+|-)?(?:90(?:(?:\.0{1,6})?)|(?:[0-9]|[1-8][0-9])(?:(?:\.[0-9]{1,6})?))$

위도 정규식 시각화

경도

^(\+|-)?(?:180(?:(?:\.0{1,6})?)|(?:[0-9]|[1-9][0-9]|1[0-7][0-9])(?:(?:\.[0-9]{1,6})?))$

경도 정규식 시각화


다음 은 액세스 용이성을 위해 두 가지를 모두 테스트하는 요지입니다. Java TestNG 테스트입니다. Slf4j, Hamcrest 및 Lombok이 필요합니다.

import static org.hamcrest.Matchers.*;
import static org.hamcrest.MatcherAssert.*;

import java.math.RoundingMode;
import java.text.DecimalFormat;

import lombok.extern.slf4j.Slf4j;

import org.testng.annotations.Test;

@Slf4j
public class LatLongValidationTest {

    protected static final String LATITUDE_PATTERN="^(\\+|-)?(?:90(?:(?:\\.0{1,6})?)|(?:[0-9]|[1-8][0-9])(?:(?:\\.[0-9]{1,6})?))$";
    protected static final String LONGITUDE_PATTERN="^(\\+|-)?(?:180(?:(?:\\.0{1,6})?)|(?:[0-9]|[1-9][0-9]|1[0-7][0-9])(?:(?:\\.[0-9]{1,6})?))$";

    @Test
    public void latitudeTest(){
        DecimalFormat df = new DecimalFormat("#.######");
        df.setRoundingMode(RoundingMode.UP);
        double step = 0.01;
        Double latitudeToTest = -90.0;

        while(latitudeToTest <= 90.0){
            boolean result = df.format(latitudeToTest).matches(LATITUDE_PATTERN);
            log.info("Latitude: tested {}. Result (matches regex): {}", df.format(latitudeToTest), result);
            assertThat(result, is(true));
            latitudeToTest += step;
        }

        latitudeToTest = -90.1;

        while(latitudeToTest >= -200.0){
            boolean result = df.format(latitudeToTest).matches(LATITUDE_PATTERN);
            log.info("Latitude: tested {}. Result (matches regex): {}", df.format(latitudeToTest), result);
            assertThat(result, is(false));
            latitudeToTest -= step;
        }

        latitudeToTest = 90.01;

        while(latitudeToTest <= 200.0){
            boolean result = df.format(latitudeToTest).matches(LATITUDE_PATTERN);
        log.info("Latitude: tested {}. Result (matches regex): {}", df.format(latitudeToTest), result);
            assertThat(result, is(false));
            latitudeToTest += step;
        }
    }

    @Test
    public void longitudeTest(){
        DecimalFormat df = new DecimalFormat("#.######");
        df.setRoundingMode(RoundingMode.UP);
        double step = 0.01;
        Double longitudeToTest = -180.0;

        while(longitudeToTest <= 180.0){
            boolean result = df.format(longitudeToTest).matches(LONGITUDE_PATTERN);
            log.info("Longitude: tested {}. Result (matches regex): {}", df.format(longitudeToTest), result);
            assertThat(result, is(true));
            longitudeToTest += step;
        }

        longitudeToTest = -180.01;

        while(longitudeToTest >= -300.0){
            boolean result = df.format(longitudeToTest).matches(LONGITUDE_PATTERN);
            log.info("Longitude: tested {}. Result (matches regex): {}", df.format(longitudeToTest), result);
            assertThat(result, is(false));
            longitudeToTest -= step;
        }

        longitudeToTest = 180.01;

        while(longitudeToTest <= 300.0){
            boolean result = df.format(longitudeToTest).matches(LONGITUDE_PATTERN);
            log.info("Longitude: tested {}. Result (matches regex): {}", df.format(longitudeToTest), result);
            assertThat(result, is(false));
            longitudeToTest += step;
        }
    }
}

이것은 정말 좋은 정규식이었습니다! 그러나 조금 줄일 수 있습니까? :) 그것이 가능하지 않다면, 그것은 괜찮지 만 단축 코드는 언제나 환영합니다 :)
— Airikr

@ErikEdgren 나는 그것을 단축하는 방법을 찾지 못했습니다 :(
— Marco Ferrari

1
알았어. 정규식은 여전히 ​​굉장합니다;)
— Airikr

2
nice visual : D이 웹 사이트에 대해 몰랐습니다! 감사합니다 !
— Damiii

— SO

19

실제로 정규식 위의 Alix Axel은 위도, 경도 범위의 관점에서 잘못되었습니다.

위도 측정 범위는 –90 ° ~ + 90 °입니다. 경도 측정 범위는 –180 ° ~ + 180 °입니다.

따라서 아래에 주어진 정규식이 더 정확하게 검증됩니다.
또한 내 생각에 따라 아무도 위도 / 경도로 소수점을 제한해서는 안됩니다.

^([-+]?\d{1,2}([.]\d+)?),\s*([-+]?\d{1,3}([.]\d+)?)$

또는 목표 C의 경우

^([-+]?\\d{1,2}([.]\\d+)?),\\s*([-+]?\\d{1,3}([.]\\d+)?)$

2
그것은 수용 99을위한 Latitude동안 99의 범위를 벗어 -90, +90때문에 무효.
— ako

14
^-?[0-9]{1,3}(?:\.[0-9]{1,10})?$

정규식 분석 :

^-?[0-9]{1,3}(?:\.[0-9]{1,10})?$

-? # 음수 값 허용

^ # 문자열의 시작

[0-9]{1,3} # 1 ~ 3 자리 숫자 (예 : 0-999)

(?: # 일치하려고 ...

\. # 소수점

[0-9]{1,10} # 다음에 1 ~ 10 자리 숫자 (예 : 0-9999999999)

)? # ... 선택적으로

$ # 문자열의 끝


나는 당신이 가장 우아하다고 생각합니다. 첫째, 이스케이프 문자를 편집하고 바꿀 필요없이 즉시 작동했습니다. 둘째, 짧습니다. 셋째, 이해하기 쉽습니다.
— Jim Rota

9

이 시도:

^(\()([-+]?)([\d]{1,2})(((\.)(\d+)(,)))(\s*)(([-+]?)([\d]{1,3})((\.)(\d+))?(\)))$

다음에서 확인하십시오.

http://regexpal.com/

상단 상자에 표현식을 붙여 넣은 다음 하단 상자에 다음과 같은 것을 넣습니다.

(80.0123, -34.034)
(80.0123)
(80.a)
(980.13, 40)
(99.000, 122.000)

정규식 분석 :

^                    # The string must start this way (there can't be anything before). 
    (\()             # An opening parentheses (escaped with a backslash).
    ([-+]?)          # An optional minus, or an optional plus.
    ([\d]{1,2})      # 1 or 2 digits (0-9).
    (                # Start of a sub-pattern.
        (            # Start of a sub-pattern.
            (\.)     # A dot (escaped with a backslash).
            (\d+)    # One or more digits (0-9).
            (,)      # A comma.
        )            # End of a sub-pattern.
    )                # End of a sub-pattern.
    (\s*)            # Zero or more spaces.
    (                # Start of a sub-pattern.
        ([-+]?)      # An optional minus, or an optional plus. 
        ([\d]{1,3})  # 1 to 3 digits (0-9).
        (            # Start of a pattern.
            (\.)     # A dot (escaped with a backslash).
            (\d+)    # One or more digits (0-9).
        )?           # End of an optional pattern.
        (\))         # A closing parenthesis (escaped with a backkslash).
    )                # End of a pattern
$                    # The string must end this way (there can't be anything after).

이제 이것이하지 않는 것은 스스로를이 범위로 제한하는 것입니다.

(-90 to +90, and -180 to +180)

대신 간단하게이 범위로 제한됩니다.

(-99 to +99, -199 to +199) 

그러나 요점은 주로 표현의 각 부분을 분해하는 것입니다.


7

보다 엄격한 버전은 다음과 같습니다.

^([-+]?\d{1,2}[.]\d+),\s*([-+]?\d{1,3}[.]\d+)$
  • 위도 = -90-+90
  • 경도 = -180-+180

1
나는 {1,2}가 먼저오고 나서 {1,3}이되어야한다고 믿습니다
— randunel

@Arjan : 고정, 나는 항상 두 가지를 혼동합니다. 감사!
— Alix Axel

5

파이썬 :

위도: result = re.match("^[+-]?((90\.?0*$)|(([0-8]?[0-9])\.?[0-9]*$))", '-90.00001')

경도: result = re.match("^[+-]?((180\.?0*$)|(((1[0-7][0-9])|([0-9]{0,2}))\.?[0-9]*$))", '-0.0000')

예제에서 위도는 실패해야합니다.


4

@ macro-ferrari 나는 그것을 단축시키는 방법을 찾았으며, 정규식 엔진에 대한 최근의 모든 대화에 비추어 미리 보지 않고

const LAT_RE = /^[+-]?(([1-8]?[0-9])(\.[0-9]{1,6})?|90(\.0{1,6})?)$/;

여기에 이미지 설명을 입력하십시오

const LONG_RE = /^[+-]?((([1-9]?[0-9]|1[0-7][0-9])(\.[0-9]{1,6})?)|180(\.0{1,6})?)$/;

여기에 이미지 설명을 입력하십시오


좋은 설명, 어떻게이 흐름 제어를 사용하여 특정 소프트웨어를 어떻게 사용 했습니까? 이 하나의 regexper.com ?
— silentsudo 2018 년

3

\ s (공백)를 사용해야하는 \ w (단어 문자)를 사용하고 있다고 생각합니다. 단어 문자는 일반적으로 [A-Za-z0-9_]로 구성되므로 공백을 제외하고 선택적인 빼기 부호 나 숫자에서 더 이상 일치하지 않습니다.


3

이것은 다음과 같은 형식으로 작동합니다. 31 ͦ 37.4 'E

^[-]?\d{1,2}[ ]*ͦ[ ]*\d{1,2}\.?\d{1,2}[ ]*\x27[ ]*\w$

1

루비

경도 -179.99999999..180

/^(-?(?:1[0-7]|[1-9])?\d(?:\.\d{1,8})?|180(?:\.0{1,8})?)$/ === longitude.to_s

위도 -89.99999999..90

/^(-?[1-8]?\d(?:\.\d{1,8})?|90(?:\.0{1,8})?)$/ === latitude.to_s

0

위도 및 경도에 대한 올바른 패턴을 확인하기 위해 목표 C에서 완전하고 간단한 방법은 다음과 같습니다.

 -( BOOL )textIsValidValue:(NSString*) searchedString
{
    NSRange   searchedRange = NSMakeRange(0, [searchedString length]);
    NSError  *error = nil;
    NSString *pattern = @"^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?),\\s*[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)$";
    NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern: pattern options:0 error:&error];
    NSTextCheckingResult *match = [regex firstMatchInString:searchedString options:0 range: searchedRange];
    return match ? YES : NO;
}

여기서 searchedString 은 사용자가 해당 텍스트 필드에 입력하는 입력입니다.


0

PHP

다음은 PHP 버전입니다 (입력 값 : $latitude및 $longitude).

$latitude_pattern  = '/\A[+-]?(?:90(?:\.0{1,18})?|\d(?(?<=9)|\d?)\.\d{1,18})\z/x';
$longitude_pattern = '/\A[+-]?(?:180(?:\.0{1,18})?|(?:1[0-7]\d|\d{1,2})\.\d{1,18})\z/x';
if (preg_match($latitude_pattern, $latitude) && preg_match($longitude_pattern, $longitude)) {
  // Valid coordinates.
}

-1

당신은 이것을 시도 할 수 있습니다 :

var latExp = /^(?=.)-?((8[0-5]?)|([0-7]?[0-9]))?(?:\.[0-9]{1,20})?$/;
var lngExp = /^(?=.)-?((0?[8-9][0-9])|180|([0-1]?[0-7]?[0-9]))?(?:\.[0-9]{1,20})?$/;

-2

이 시도:

^[-+]?(([0-8]\\d|\\d)(\\.\\d+)?|90(\\.0+)?)$,\s*^[-+]?((1[0-7]\\d(\\.\\d+)?)|(180(\\.0+)?)|(\\d\\d(\\.\\d+)?)|(\\d(\\.\\d+)?))$

-2

이 시도:

(?<!\d)([-+]?(?:[1-8]?\d(?:\.\d+)?|90(?:\.0+)?)),\s*([-+]?(?:180(?:\.0+)?|(?:(?:1[0-7]\d)|(?:[1-9]?\d))(?:\.\d+)?))(?!\d)`

5
순수한 코드 답변은 거의 좋은 생각이 아닙니다. 답변에 설명 텍스트를 추가하십시오.
— timclutton

훌륭하게 작동합니다. 모든 텍스트에서 정확하게 유효성을 검사하고 위도를 선택합니다. 그러나 소수점 이후에 허용되는 유효 자릿수를 제한하지는 않습니다.
— user4325241
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.