用于匹配纬度/经度坐标的正则表达式?


149

我正在尝试创建一个正则表达式来匹配纬度/经度坐标。为了匹配双精度数,我使用(\-?\d+(\.\d+)?),并尝试将其组合为单个表达式:

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

我希望它能匹配一个双精度字母,一个逗号,可能还有一些空格和另一个双精度像素,但它似乎不起作用。具体来说,它仅在没有空间的情况下才有效,而不是一个或多个。我做错了什么?

Answers:


117

空格是\ s,而不是\ w

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

看看是否可行


1
我必须使用点而不是逗号:/^(\-?\d+(\.\d+)?)hereAdot。endMod \ s *(\-?\ d +(\。\ d +)?)$ /
kolodi's

它接受超出经度和纬度范围的值。例如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

这太棒了。范围检查的荣誉。
radj 2015年

1
我认为您的第一个比赛示例中有错字。我怀疑RegEx是否会匹配3个值。
2015年

固定。这本来是两个单独的示例。
伊恩·弗雷泽

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+)?))$
延迟时间

108

我正在使用这些(十进制格式,带有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;
        }
    }
}

这是一个非常好的正则表达式!但是有可能将其缩短一点吗?:)如果不能,那就好了,但是总是欢迎使用
较短的

@ErikEdgren我没有找到缩短它的方法:(
Marco Ferrari

1
好吧:/哦,很好。您的正则表达式仍然很棒;)
Airikr 2015年

2
不错的视觉效果:D对该网站不了解!谢谢 !
Damiii '16

什么是网站网址
的K -毒性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
它接受99Latitude,虽然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 2015年

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

蟒蛇:

纬度: 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

我相信您在应该使用\ 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.
}


-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 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.