Регулярное выражение для соответствия координат широты и долготы?


149

Я пытаюсь создать регулярное выражение для соответствия координат широты и долготы. Для сопоставления числа с двойной точностью я использовал (\-?\d+(\.\d+)?)и попытался объединить это в одно выражение:

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

Я ожидал, что это будет совпадать с двойным, запятой, возможно, некоторым пробелом и другим двойным, но, похоже, это не сработает. В частности, это работает только если нет места, а не один или несколько. Что я сделал не так?

Ответы:


117

Пробел это \ s, а не \ w

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

Посмотрите, работает ли это


1
Мне пришлось использовать точку вместо запятой: /^(\-?\d+(\.\d+)?) Здесь Adot. endMod \ s * (\ -? \ d + (\. \ d +)?) $ /
kolodi

Он принимает значения вне допустимого диапазона для латов и длин. например, 91 181
Арун Карунагат

Это работает и для 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

Это круто. Престижность для диапазона проверки включения.
Радия

1
Я думаю, у вас есть опечатка в вашем первом примере матчей. Я сомневаюсь, что RegEx будет соответствовать 3 значениям.
Буркхард

Исправлена. Предполагалось, что это будет два отдельных примера.
Иэн Фрейзер

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

110

Я использую эти (десятичный формат, с 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 Я не нашел способа его сократить :(
Марко Феррари

1
Хорошо: / Хорошо. Ваше регулярное выражение все еще потрясающе;)
Airikr

2
хороший визуальный: D Не знал об этом сайте! Спасибо !
Дамии

Что такое веб-сайт url
K - Токсичность в SO растет.

19

На самом деле Аликс Аксель, вышеприведенное регулярное выражение неверно по широте, долготе колеблется с точки зрения.

Диапазон измерений широты от –90 ° до + 90 ° Диапазон измерений широты от –180 ° до + 180 °

Таким образом, приведенное ниже регулярное выражение проверяет более точно.
Кроме того, согласно моей мысли, никто не должен ограничивать десятичную точку по широте / долготе.

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

ИЛИ для Цели С

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

2
Он принимает 99на Latitude, в то время как 99находится вне диапазона -90, +90и поэтому недействителен.
АКО

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)

)? # ...необязательно

$ # Конец строки


Я думаю, что ваш самый элегантный. Во-первых, это сработало сразу, без необходимости редактировать и заменять escape-символы. Во-вторых, это коротко. В-третьих, это легко понять.
Джим Рота

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) 

Но главное - это просто разбить каждый фрагмент выражения.



5

Python:

Широта: 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

3

Я полагаю, что вы используете \ w (символ слова) там, где вы должны использовать \ s (пробел). Символы слова, как правило, состоят из [A-Za-z0-9_], что исключает ваш пробел, который в дальнейшем не совпадает с дополнительным знаком минус или цифрой.


3

Это будет работать для такого формата: 31 ͦ 37,4 'E

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

1

Рубин

Долгота -179,999999999,10

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

Широта -89,999999999,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;
}

где искомая строка - это ввод, который пользователь вводит в соответствующее текстовое поле.


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

прекрасно работает: точно проверяет и выбирает lat, long из любого окружающего текста. Однако не ограничивает количество значащих цифр, которые оно допускает после десятичной точки.
user4325241
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.