Regulärer Ausdruck zum Abgleichen von Längen- / Breitengradkoordinaten?

149

Ich versuche, einen regulären Ausdruck für übereinstimmende Längen- / Breitengradkoordinaten zu erstellen. Um eine Zahl mit doppelter Genauigkeit abzugleichen, habe ich (\-?\d+(\.\d+)?)versucht, diese zu einem einzigen Ausdruck zu kombinieren:

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

Ich habe erwartet, dass dies mit einem Doppel, einem Komma, vielleicht etwas Leerzeichen und einem weiteren Doppel übereinstimmt, aber es scheint nicht zu funktionieren. Insbesondere funktioniert es nur, wenn KEIN Speicherplatz vorhanden ist, nicht einer oder mehrere. Was habe ich falsch gemacht?

Jake Petroules
quelle

Antworten:

117

Leerzeichen sind \ s, nicht \ w

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

Überprüfen Sie, ob dies funktioniert

Eric C.
quelle
1
Ich musste Punkt anstelle von Komma verwenden: /^(\-?\d+(\.\d+)?) HereAdot. endMod \ s * (\ -? \ d + (\. \ d +)?) $ /
kolodi
Es akzeptiert Werte außerhalb des zulässigen Bereichs für Lats und Longs. zB 91.181
Arun Karunagath
Dies funktioniert auch für x / y-Koordinaten von projizierten Raumbezugssystemen
DeEgge
218

Dieser Wert entspricht genau den Breiten- und Längengraden, die in den richtigen Bereich fallen:

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

Streichhölzer

  • +90,0, -127,554334
  • 45, 180
  • -90, -180
  • -90.000, -180.0000
  • +90, +180
  • 47.1231231, 179.99999999

Passt nicht zusammen

  • -90., -180.
  • +90,1, -100,111
  • -91, 123,456
  • 045, 180
Iain Fraser
quelle
Das ist fantastisch. Ein großes Lob für die Aufnahme der Reichweitenprüfung.
Radj
1
Ich denke, Sie haben einen Tippfehler in Ihrem Beispiel für die ersten Spiele. Ich bezweifle, dass der RegEx 3 Werten entspricht.
Burkhard
Fest. Es sollten zwei getrennte Beispiele sein.
Iain Fraser
7
Geändert, um Leerzeichen auf beiden Seiten des Kommas zu akzeptieren: ^ [- +]? ([1-8]? \ D (\. \ D +)? | 90 (\. 0 +)?) \ S *, \ s * [- +]? (180 (\. 0 +)? | ((1 [0-7] \ d) | ([1-9]? \ d)) (\. \ d +)?) $
Puddinman13
2
Ich habe dies geändert, um genau das Lat Lon in den Erfassungsgruppen zu erhalten, indem ich die ?:Syntax der nicht erfassenden Gruppe sowie die Erfassungspolarität verwendet habe(^[-+]?(?:[1-8]?\d(?:\.\d+)?|90(?:\.0+)?)),\s*([-+]?(?:180(?:\.0+)?|(?:(?:1[0-7]\d)|(?:[1-9]?\d))(?:\.\d+)?))$
narthur157
107

Ich benutze diese (Dezimalformat mit 6 Dezimalstellen):

Breite

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

Latitude Visualisierung regulärer Ausdrücke

Längengrad

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

Longitude Visualisierung des regulären Ausdrucks


Hier ist ein Kern, der beide, auch hier berichteten, auf einfachen Zugriff testet. Es ist ein Java TestNG-Test. Sie benötigen Slf4j, Hamcrest und Lombok, um es auszuführen:

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;
        }
    }
}
Marco Ferrari
quelle
Das war eine wirklich schöne Regex! Aber ist es möglich, es ein wenig zu verkürzen? :) Wenn es nicht kann, ist es in Ordnung, aber Kurzcode ist immer willkommen :)
Airikr
@ErikEdgren Ich habe keinen Weg gefunden, es zu verkürzen :(
Marco Ferrari
1
OK, na ja. Ihre Regex ist immer noch fantastisch;)
Airikr
2
schönes Bild: D Wusste nichts von dieser Website! Danke !
Damiii
Was ist die Website URL
K - Toxizität in SO wächst.
19

Tatsächlich ist Alix Axel, oberhalb von Regex, in Bezug auf Breiten- und Längengrade falsch.

Breitengradmessungen reichen von –90 ° bis + 90 °. Längengradmessungen reichen von –180 ° bis + 180 °

Der unten angegebene reguläre Ausdruck wird also genauer validiert.
Meiner Meinung nach sollte niemand den Dezimalpunkt in Längen- und Breitengrad einschränken.

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

ODER für Ziel C.

^([-+]?\\d{1,2}([.]\\d+)?),\\s*([-+]?\\d{1,3}([.]\\d+)?)$
Sampada
quelle
2
Es akzeptiert 99für Latitude, während 99außerhalb des Bereichs von -90, +90und so ungültig ist.
Ako
14
^-?[0-9]{1,3}(?:\.[0-9]{1,10})?$

Regex-Aufschlüsselung:

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

-? # negative Werte akzeptieren

^ # Beginn der Zeichenfolge

[0-9]{1,3} # Übereinstimmung mit 1-3 Ziffern (dh 0-999)

(?: # Versuchen Sie zu passen ...

\. # ein Dezimalpunkt

[0-9]{1,10} # gefolgt von einer bis 10 Ziffern (dh 0-9999999999)

)? # ... optional

$ # Ende der Zeichenfolge

Zehra Nasif
quelle
Ich denke, deine ist die eleganteste. Erstens funktionierte es sofort, ohne dass Escape-Zeichen bearbeitet und ersetzt werden mussten. Zweitens ist es kurz. Drittens ist es leicht zu verstehen.
Jim Rota
9

Versuche dies:

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

Schau es dir an unter:

http://regexpal.com/

Fügen Sie den Ausdruck in das obere Feld ein und fügen Sie dann Folgendes in das untere Feld ein:

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

Regex-Aufschlüsselung:

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

Dies beschränkt sich NICHT auf diesen Bereich:

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

Stattdessen beschränkt es sich einfach auf diesen Bereich:

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

Es geht aber hauptsächlich darum, jedes Stück des Ausdrucks zu zerlegen.

user1439929
quelle
7

Hier ist eine strengere Version:

^([-+]?\d{1,2}[.]\d+),\s*([-+]?\d{1,3}[.]\d+)$
  • Breitengrad = -90-+90
  • Längengrad = -180-+180
Alix Axel
quelle
1
Ich glaube, dass {1,2} zuerst kommen sollte, dann {1,3}
Randunel
@Arjan: Behoben, ich verwechsle die beiden immer. Vielen Dank!
Alix Axel
5

Python:

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

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

Latitude sollte im Beispiel fehlschlagen.

picmate 涅
quelle
4

@ macro-ferrari Ich habe einen Weg gefunden, es zu verkürzen, und ohne vorausschauend angesichts all der jüngsten Gespräche über Regex-Engines

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

Geben Sie hier die Bildbeschreibung ein

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

Geben Sie hier die Bildbeschreibung ein

Arun Karunagath
quelle
Schöne Erklärung, übrigens, wie haben Sie diese Flusskontrolle zu einer bestimmten Software bekommen, die Sie verwendet haben? dieser eine regexper.com ?
Silentsudo
3

Ich glaube, Sie verwenden \ w (Wortzeichen), wo Sie \ s (Leerzeichen) verwenden sollten. Wortzeichen bestehen normalerweise aus [A-Za-z0-9_], sodass Ihr Leerzeichen ausgeschlossen wird, das dann nicht mit dem optionalen Minuszeichen oder einer Ziffer übereinstimmt.

Theraccoonbear
quelle
3

Dies würde für ein Format wie das folgende funktionieren: 31 ͦ 37.4 'E.

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

Rubin

Längengrad -179.99999999..180

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

Breitengrad -89.99999999..90

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

Eine vollständige und einfache Methode in Ziel C zur Überprüfung des korrekten Musters auf Längen- und Breitengrad ist:

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

wobei SearchedString ist der Eingang , dass der Benutzer in dem jeweiligen Kästchen ein würde.

saxenarishav
quelle
0

PHP

Hier ist die PHP-Version (Eingabewerte sind: $latitudeund $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.
}
Kenorb
quelle
-1

Sie können dies versuchen:

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})?$/;
Sagar Mal Shankhala
quelle
-2

Versuche dies:

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

Versuche dies:

(?<!\d)([-+]?(?:[1-8]?\d(?:\.\d+)?|90(?:\.0+)?)),\s*([-+]?(?:180(?:\.0+)?|(?:(?:1[0-7]\d)|(?:[1-9]?\d))(?:\.\d+)?))(?!\d)`
user4325241
quelle
5
Reine Code-Antworten sind selten eine gute Idee. Bitte fügen Sie Ihrer Antwort einen beschreibenden Text hinzu.
Timclutton
funktioniert hervorragend: validiert genau und wählt lat, long aus jedem umgebenden Text aus. Beschränkt jedoch nicht die Anzahl der signifikanten Stellen, die nach dem Dezimalpunkt zulässig sind.
user4325241