Espressione regolare per la corrispondenza delle coordinate di latitudine / longitudine?


149

Sto cercando di creare un'espressione regolare per abbinare le coordinate di latitudine / longitudine. Per abbinare un numero a doppia precisione che ho usato (\-?\d+(\.\d+)?)e ho provato a combinarlo in una singola espressione:

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

Mi aspettavo che corrispondesse a un doppio, una virgola, forse un po 'di spazio e un altro doppio, ma non sembra funzionare. In particolare funziona solo se NON c'è spazio, non uno o più. Cosa ho fatto di sbagliato?

Risposte:


117

Lo spazio bianco è \ s, non \ w

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

Vedi se funziona


1
Ho dovuto usare il punto anziché la virgola: /^(\-?\d+(\.\d+)?) QuiAdot. endMod \ s * (\ -? \ d + (\. \ d +)?) $ /
kolodi

Accetta valori al di fuori dell'intervallo consentito per lat e long. ad esempio, 91.181
Arun Karunagath

Questo funziona anche per le coordinate x / y dei sistemi di riferimento spaziale proiettati
DeEgge

218

Questo corrisponderà rigorosamente ai valori di latitudine e longitudine che rientrano nell'intervallo corretto:

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

fiammiferi

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

Non corrisponde

  • -90., -180.
  • +90,1, -100,111
  • -91, 123.456
  • 045, 180

Questo e spettacolare. Complimenti per l'inclusione del controllo della gamma.
Radj,

1
Penso che tu abbia un refuso nell'esempio delle tue prime partite. Dubito che RegEx corrisponderà a 3 valori.
Burkhard,

Fisso. Doveva essere due esempi separati.
Iain Fraser,

7
Modificato per accettare spazi bianchi su entrambi i lati della virgola: ^ [- +]? ([1-8]? \ D (\. \ D +)? | 90 (\. 0 +)?) \ S *, \ s * [- +]? (180 (\. 0 +)? | ((1 [0-7] \ d) | ([1-9]? \ d)) (\. \ d +)?) $
puddinman13

2
Ho cambiato questo per ottenere solo quel lat lon nei gruppi di acquisizione utilizzando la ?:sintassi del gruppo non di acquisizione, nonché la polarità di acquisizione(^[-+]?(?:[1-8]?\d(?:\.\d+)?|90(?:\.0+)?)),\s*([-+]?(?:180(?:\.0+)?|(?:(?:1[0-7]\d)|(?:[1-9]?\d))(?:\.\d+)?))$
narthur157

109

Sto usando questi (formato decimale, con 6 cifre decimali):

Latitudine

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

Latitudine Visualizzazione delle espressioni regolari

Longitudine

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

Longitudine Visualizzazione delle espressioni regolari


Ecco una sintesi che verifica entrambi, riportati anche qui, per un facile accesso. È un test Java TestNG. Hai bisogno di Slf4j, Hamcrest e Lombok per eseguirlo:

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

È stata davvero una bella regex! Ma è possibile accorciarlo un po '? :) Se non può, è okey ma accorciare il codice è sempre il benvenuto :)
Airikr

@ErikEdgren Non ho trovato un modo per accorciarlo :(
Marco Ferrari,

1
Ok: / Oh bene. Il tuo regex è ancora fantastico;)
Airikr,

2
bella grafica: D Non sapevo di questo sito! Grazie !
Damiii,

Qual è il sito web url
K - La tossicità in SO sta crescendo.

19

In realtà Alix Axel, al di sopra di regex, è errato nel punto di vista della latitudine e della longitudine.

Le misurazioni della latitudine vanno da –90 ° a + 90 ° Le misurazioni della longitudine vanno da –180 ° a + 180 °

Quindi la regex indicata di seguito viene convalidata in modo più accurato.
Inoltre, secondo il mio pensiero, nessuno dovrebbe limitare il punto decimale in latitudine / longitudine.

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

OPPURE per l'obiettivo C

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

2
Accetta 99per Latitude, mentre 99è fuori portata -90, +90e quindi non valido.
ako,

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

Ripartizione Regex:

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

-? # accetta valori negativi

^ # Inizio della stringa

[0-9]{1,3} # Abbina 1-3 cifre (ovvero 0-999)

(?: # Prova ad abbinare ...

\. # un punto decimale

[0-9]{1,10} # seguito da una a 10 cifre (ovvero 0-9999999999)

)? # ... facoltativamente

$ # Fine della stringa


Penso che il tuo sia il più elegante. In primo luogo, ha funzionato immediatamente senza dover modificare e sostituire i caratteri di escape. In secondo luogo, è breve. In terzo luogo, è facile da capire.
Jim Rota,

9

Prova questo:

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

Dai un'occhiata a:

http://regexpal.com/

Incolla l'espressione nella casella in alto, quindi inserisci cose come questa nella casella in basso:

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

Ripartizione 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).

Ora, ciò che NON fa è limitarsi a questo intervallo:

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

Invece, si limita a questo intervallo:

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

Ma il punto è principalmente solo quello di abbattere ogni parte dell'espressione.


7

Ecco una versione più rigorosa:

^([-+]?\d{1,2}[.]\d+),\s*([-+]?\d{1,3}[.]\d+)$
  • Latitudine = -90-+90
  • Longitudine = -180-+180

1
Credo che {1,2} dovrebbe venire prima, quindi {1,3}
randunel

@Arjan: risolto, confondo sempre i due. Grazie!
Alix Axel,

5

Pitone:

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

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

La latitudine dovrebbe fallire nell'esempio.


4

@ macro-ferrari ho trovato un modo per accorciarlo, e senza guardare avanti alla luce di tutti i recenti discorsi sui motori regex

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

inserisci qui la descrizione dell'immagine

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

inserisci qui la descrizione dell'immagine


Bella spiegazione, tra l'altro come hai ottenuto questo controllo di flusso qualsiasi software specifico che hai usato. questo regexper.com ?
silentsudo

3

Credo che tu stia usando \ w (carattere di parola) dove dovresti usare \ s (spazi bianchi). I caratteri di parole in genere sono costituiti da [A-Za-z0-9_], quindi questo esclude il tuo spazio, che quindi non riesce più a corrispondere sul segno meno opzionale o su una cifra.


3

Funzionerebbe con un formato come questo: 31 ͦ 37,4 'E

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

1

Rubino

Longitudine -179.99999999..180

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

Latitudine -89.99999999..90

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

0

Un metodo completo e semplice nell'obiettivo C per verificare il modello corretto di latitudine e longitudine è:

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

dove searchedString è l'ingresso che l'utente potrebbe inserire nel rispettivo campo di testo.


0

PHP

Ecco la versione di PHP (i valori di input sono: $latitudee $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

Puoi provare questo:

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

Prova questo:

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

-2

Prova questo:

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

5
Le risposte pure al codice sono raramente una buona idea. Aggiungi un testo descrittivo alla tua risposta.
Timclutton,

funziona alla grande: convalida accuratamente e seleziona lat, a lungo da qualsiasi testo circostante. Tuttavia, non limita il numero di cifre significative che consente dopo il punto decimale.
user4325241
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.