緯度/経度座標を照合するための正規表現?


149

緯度/経度座標を照合するための正規表現を作成しようとしています。私が使用した倍精度数を照合する(\-?\d+(\.\d+)?)ために、それを単一の式に組み合わせようとしました:

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

これはダブル、コンマ、おそらくスペース、および別のダブルに一致すると期待していましたが、機能しないようです。具体的には、1つ以上ではなく、スペースがない場合にのみ機能します。何が悪いのでしょうか?

回答:


117

空白は\ sではなく\ sです

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

これが機能するかどうかを確認します


1
コンマの代わりにドットを使用する必要がありました:/^(\-?\d+(\.\d+)?)hereAdot。endMod \ s *(\-?\ d +(\。\ d +)?)$ /
kolodi 2016年

緯度と経度の許容範囲外の値を受け入れます。例: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

修繕。これは、2つの別個の例であることを意味していました。
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桁の10進数):

緯度

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

Latitude正規表現の視覚化

経度

^(\+|-)?(?: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私はそれを短縮する方法を見つけませんでした:(
マルコフェラーリ

1
わかりました:/まあ。あなたの正規表現はまだ素晴らしいです;)
Airikr '10 / 10/15

2
素敵なビジュアル:Dこのウェブサイトについて知りませんでした!ありがとうございました !
Damiii 2016

ウェブサイトのURLは何ですか
K-SOの毒性が高まっています。

19

実際には、正規表現の上にあるAlix Axelは、緯度、経度の範囲の観点では間違っています。

緯度の測定範囲は–90°〜+ 90°経度の測定範囲は–180°〜+ 180°

したがって、以下の正規表現はより正確に検証されます。
また、私の考えに従って、緯度/経度の小数点を制限するべきではありません。

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

またはObjective C

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

2
を受け入れます99Latitude99範囲外の-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)

)? #...オプションで

$ #文字列の終わり


私はあなたが一番エレガントだと思います。まず、エスケープ文字を編集したり置き換えたりせずにすぐに機能しました。第二に、それは短いです。第三に、それは理解しやすいです。
ジム・ロタ

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}が来ると信じています
ランデュネル2013

@Arjan:修正済み、私は常にこの2つを混同します。ありがとう!
Alix Axel

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')

この例ではLatitudeが失敗するはずです。


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

-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

これを試して:

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

5
純粋なコードの回答が推奨されることはめったにありません。解答に説明文を追加してください。
timclutton 2014

正しく機能します。正確に検証し、周囲のテキストから長い緯度を選択します。ただし、小数点以下の有効桁数は制限されません。
user4325241 2014
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.