Biểu thức chính quy cho tọa độ vĩ độ / kinh độ phù hợp?


149

Tôi đang cố gắng tạo một biểu thức chính quy cho các tọa độ vĩ độ / kinh độ phù hợp. Để khớp số chính xác kép mà tôi đã sử dụng (\-?\d+(\.\d+)?)và đã thử kết hợp số đó thành một biểu thức duy nhất:

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

Tôi hy vọng điều này sẽ khớp với một dấu phẩy, dấu phẩy, có thể là một khoảng trắng và một dấu đôi khác, nhưng dường như nó không hoạt động. Cụ thể nó chỉ hoạt động nếu KHÔNG có không gian, không phải một hoặc nhiều. Tôi đã làm gì sai?

Câu trả lời:


117

Khoảng trắng là \ s, không phải \ w

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

Xem nếu điều này làm việc


1
Tôi đã phải sử dụng dấu chấm thay vì dấu phẩy: / ^ (\ -? \ D + (\. \ D +)?) Ở đâyAdot. endMod \ s * (\ -? \ d + (\. \ d +)?) $ /
kolodi

Nó chấp nhận các giá trị bên ngoài phạm vi được phép cho lats và longs. ví dụ: 91,181
Arun Karunagath

Điều này cũng hoạt động cho tọa độ x / y của các hệ quy chiếu không gian dự kiến
DeEgge

218

Điều này sẽ hoàn toàn khớp với các giá trị vĩ độ và kinh độ nằm trong phạm vi chính xác:

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

Diêm

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

Không phù hợp

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

Điều này thật tuyệt. Kudos cho bao gồm kiểm tra phạm vi.
radj 23/2/2015

1
Tôi nghĩ rằng bạn có một lỗi đánh máy trong ví dụ trận đấu đầu tiên của bạn. Tôi nghi ngờ rằng RegEx sẽ khớp với 3 giá trị.
Burkhard

Đã sửa. Nó có nghĩa là hai ví dụ riêng biệt.
Iain Fraser

7
Được sửa đổi để chấp nhận khoảng trắng ở cả hai bên của dấu phẩy: ^ [- +]? ([1-8]? \ D (\. \ D +)? | 90 (\. 0 +)?) \ S *, \ s * [- +]? (180 (\. 0 +)? | ((1 [0-7] \ d) | ([1-9]? \ d)) (\. \ d +)?) $
puddinman13

2
Tôi đã thay đổi điều này để có được lat lat trong các nhóm bắt bằng cách sử dụng ?:cú pháp nhóm không bắt, cũng như bắt cực(^[-+]?(?:[1-8]?\d(?:\.\d+)?|90(?:\.0+)?)),\s*([-+]?(?:180(?:\.0+)?|(?:(?:1[0-7]\d)|(?:[1-9]?\d))(?:\.\d+)?))$
narthur157

108

Tôi đang sử dụng những cái này (định dạng thập phân, có 6 chữ số thập phân):

Vĩ độ

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

Trực quan hóa biểu thức chính quy

Kinh độ

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

Kinh độ Hình dung biểu thức chính quy


Đây là một ý chính kiểm tra cả hai, cũng được báo cáo ở đây, để dễ truy cập. Đây là một thử nghiệm Java TestNG. Bạn cần Slf4j, Hamcrest và Lombok để chạy nó:

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;
        }
    }
}

Đây là một regex thực sự tốt đẹp! Nhưng nó có thể rút ngắn nó xuống một chút không? :) Nếu không thể, đó là okey nhưng rút ngắn mã luôn được chào đón :)
Airikr

@ErikEdgren Tôi không tìm được cách rút ngắn :(
Marco Ferrari

1
Ok: / Ồ tốt. Regex của bạn vẫn tuyệt vời;)
Airikr

2
hình ảnh đẹp: D Không biết về trang web này! Cảm ơn bạn !
Damiii


19

Trên thực tế Alix Axel, trên regex là sai về vĩ độ, kinh độ phạm vi quan điểm.

Các phép đo vĩ độ nằm trong phạm vi từ phạm vi 9090 đến + 90 ° Phạm vi đo kinh độ từ phạm vi180 ° đến + 180 °

Vì vậy, regex đưa ra dưới đây xác nhận chính xác hơn.
Ngoài ra, theo suy nghĩ của tôi, không ai nên hạn chế dấu thập phân theo vĩ độ / kinh độ.

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

HOẶC cho mục tiêu C

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

2
Nó chấp nhận 99cho Latitude, trong khi 99là ra khỏi phạm vi của -90, +90và vì vậy không hợp lệ.
ako

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

Sự cố Regex:

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

-? # chấp nhận giá trị âm

^ # Bắt đầu chuỗi

[0-9]{1,3} # Khớp 1-3 chữ số (tức là 0-999)

(?: # Cố gắng khớp ...

\. # một dấu thập phân

[0-9]{1,10} # theo sau là một đến 10 chữ số (tức là 0-9999999999)

)? # ... tùy chọn

$ # Kết thúc chuỗi


Tôi nghĩ rằng của bạn là thanh lịch nhất. Đầu tiên, nó hoạt động ngay lập tức mà không cần phải chỉnh sửa và thay thế các ký tự thoát. Thứ hai, nó ngắn. Thứ ba, nó là dễ hiểu.
Jim Rota

9

Thử cái này:

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

Kiểm tra nó tại:

http://regExal.com/

Dán biểu thức vào hộp trên cùng, sau đó đặt những thứ như thế này vào hộp dưới cùng:

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

Sự cố Regex:

^                    # 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).

Bây giờ, điều này KHÔNG làm là giới hạn bản thân trong phạm vi này:

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

Thay vào đó, nó đơn giản giới hạn bản thân trong phạm vi này:

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

Nhưng điểm chủ yếu chỉ là phá vỡ từng phần của biểu thức.


7

Đây là một phiên bản nghiêm ngặt hơn:

^([-+]?\d{1,2}[.]\d+),\s*([-+]?\d{1,3}[.]\d+)$
  • Vĩ độ = -90-+90
  • Kinh độ = -180-+180

1
Tôi tin rằng {1,2} nên đến trước, sau đó {1,3}
randunel

@Arjan: Đã sửa, tôi luôn nhầm lẫn hai. Cảm ơn!
Alix Axel

5

Con trăn

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

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

Vĩ độ sẽ thất bại trong ví dụ.


4

@ macro-ferrari Tôi đã tìm ra cách rút ngắn nó, và không cần nhìn vào ánh sáng của tất cả các cuộc thảo luận gần đây về công cụ regex

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

nhập mô tả hình ảnh ở đây

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

nhập mô tả hình ảnh ở đây


Giải thích hay, btw làm thế nào bạn có được điều khiển luồng này bất kỳ phần mềm cụ thể nào bạn sử dụng. cái này regexper.com ?
im lặng

3

Tôi tin rằng bạn đang sử dụng \ w (ký tự từ) trong đó bạn nên sử dụng \ s (khoảng trắng). Các ký tự từ thường bao gồm [A-Za-z0-9_], do đó loại trừ không gian của bạn, sau đó không khớp với dấu trừ tùy chọn hoặc chữ số.


3

Điều này sẽ làm việc cho định dạng như thế này: 31 37,4 'E

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

1

Hồng ngọc

Kinh độ -179.99999999..180

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

Vĩ độ -89.99999999..90

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

0

Một phương pháp hoàn chỉnh và đơn giản trong mục tiêu C để kiểm tra mẫu chính xác cho vĩ độ và kinh độ là:

 -( 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;
}

trong đó searchString là đầu vào mà người dùng sẽ nhập vào trường văn bản tương ứng.


0

PHP

Đây là phiên bản của PHP (giá trị đầu vào là: $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

Bạn có thể thử điều này:

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

Thử cái này:

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

-2

Thử cái này:

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

5
Câu trả lời mã thuần túy hiếm khi là một ý tưởng tốt. Vui lòng thêm một số văn bản mô tả vào câu trả lời của bạn.
timclutton

hoạt động tuyệt vời: xác nhận chính xác và chọn lat, dài từ bất kỳ văn bản xung quanh. Tuy nhiên, không giới hạn số chữ số có nghĩa mà nó cho phép sau dấu thập phân.
dùng4325241
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.