Expression régulière pour faire correspondre les coordonnées de latitude / longitude?


149

J'essaie de créer une expression régulière pour faire correspondre les coordonnées de latitude / longitude. Pour faire correspondre un nombre à double précision que j'ai utilisé (\-?\d+(\.\d+)?), et j'ai essayé de le combiner en une seule expression:

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

Je m'attendais à ce que cela corresponde à un double, une virgule, peut-être un espace et un autre double, mais cela ne semble pas fonctionner. Plus précisément, cela ne fonctionne que s'il n'y a PAS d'espace, pas un ou plusieurs. Qu'est ce que j'ai mal fait?

Réponses:


117

L'espace blanc est \ s, pas \ w

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

Voyez si cela fonctionne


1
J'ai dû utiliser un point au lieu de la virgule: /^(\-?\d+(\.\d+)?) HereAdot. endMod \ s * (\ -? \ d + (\. \ d +)?) $ /
kolodi

Il accepte des valeurs en dehors de la plage autorisée pour les lats et les longs. par exemple, 91,181
Arun Karunagath

Cela fonctionne également pour les coordonnées x / y des systèmes de référence spatiale projetés
DeEgge

218

Celui-ci correspondra strictement aux valeurs de latitude et de longitude comprises dans la plage correcte:

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

Allumettes

  • +90,0, -127,554334
  • 45, 180
  • -90, -180
  • -90 000, -180,0000
  • +90, +180
  • 47.1231231, 179.99999999

Ne correspond pas

  • -90., -180.
  • +90.1, -100.111
  • -91, 123,456
  • 045, 180

C'est génial. Félicitations pour l'inclusion du contrôle de plage.
radj

1
Je pense que vous avez une faute de frappe dans votre premier exemple de matchs. Je doute que le RegEx corresponde à 3 valeurs.
Burkhard

Fixé. Il s'agissait de deux exemples distincts.
Iain Fraser

7
Modifié pour accepter les espaces blancs des deux côtés de la virgule: ^ [- +]? ([1-8]? \ D (\. \ D +)? | 90 (\. 0 +)?) \ S *, \ s * [- +]? (180 (\. 0 +)? | ((1 [0-7] \ d) | ([1-9]? \ d)) (\. \ d +)?) $
puddinman13

2
J'ai changé cela pour obtenir juste cette lat lon dans les groupes de capture en utilisant la ?:syntaxe de groupe non capturant, ainsi que la polarité de capture(^[-+]?(?:[1-8]?\d(?:\.\d+)?|90(?:\.0+)?)),\s*([-+]?(?:180(?:\.0+)?|(?:(?:1[0-7]\d)|(?:[1-9]?\d))(?:\.\d+)?))$
narthur157

109

J'utilise ceux-ci (format décimal, avec 6 chiffres décimaux):

Latitude

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

Visualisation des expressions régulières Latitude

Longitude

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

Visualisation des expressions régulières de longitude


Voici un résumé qui teste les deux, rapportés ici également, pour la facilité d'accès. C'est un test Java TestNG. Vous avez besoin de Slf4j, Hamcrest et Lombok pour l'exécuter:

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

C'était une très belle regex! Mais est-il possible de le raccourcir un peu? :) Si ce n'est pas le cas, ça va mais le code raccourci est toujours le bienvenu :)
Airikr

@ErikEdgren je n'ai pas trouvé de moyen de le raccourcir :(
Marco Ferrari

1
Ok: / Oh bien. Votre regex est toujours géniale;)
Airikr

2
joli visuel: D Je ne connaissais pas ce site! Je vous remercie !
Damiii

Quelle est l'url du site Web
K - La toxicité dans le SO augmente.

19

En fait, Alix Axel, au-dessus de regex, est fausse en latitude et en longitude.

Les mesures de latitude vont de –90 ° à + 90 ° Les mesures de longitude vont de –180 ° à + 180 °

Ainsi, l'expression régulière donnée ci-dessous valide plus précisément.
De plus, selon ma pensée, personne ne devrait restreindre la virgule décimale en latitude / longitude.

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

OU pour l'objectif C

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

2
Il accepte 99pour Latitude, tant qu'il 99est hors de portée -90, +90et donc invalide.
ako le

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

Répartition des expressions régulières:

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

-? # accepter les valeurs négatives

^ # Début de chaîne

[0-9]{1,3} # Correspond à 1-3 chiffres (c'est-à-dire de 0 à 999)

(?: # Essayez de faire correspondre ...

\. # un point décimal

[0-9]{1,10} # suivi d'un à 10 chiffres (par exemple 0-9999999999)

)? # ... en option

$ # Fin de chaîne


Je pense que le vôtre est le plus élégant. Premièrement, cela a fonctionné immédiatement sans avoir à modifier et à remplacer les caractères d'échappement. Deuxièmement, il est court. Troisièmement, il est facile à comprendre.
Jim Rota

9

Essaye ça:

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

Découvrez-le sur:

http://regexpal.com/

Collez l'expression dans la case du haut, puis mettez des choses comme ceci dans la case du bas:

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

Répartition des expressions régulières:

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

Maintenant, ce que cela ne fait PAS, c'est se limiter à cette plage:

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

Au lieu de cela, il se limite simplement à cette plage:

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

Mais il s'agit principalement de décomposer chaque morceau de l'expression.


7

Voici une version plus stricte:

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

1
Je crois que {1,2} devrait venir en premier, puis {1,3}
randunel

@Arjan: Corrigé, je confond toujours les deux. Merci!
Alix Axel

5

Python:

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

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

Latitude devrait échouer dans l'exemple.


4

@ macro-ferrari j'ai trouvé un moyen de le raccourcir, et sans regarder vers l'avenir à la lumière de toutes les discussions récentes sur les moteurs regex

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

entrez la description de l'image ici

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

entrez la description de l'image ici


Belle explication, btw comment avez-vous obtenu ce contrôle de flux un logiciel spécifique utilisé. celui-ci regexper.com ?
silentsudo

3

Je crois que vous utilisez \ w (caractère de mot) là où vous devriez utiliser \ s (espace). Les caractères du mot se composent généralement de [A-Za-z0-9_], ce qui exclut votre espace, qui ne correspond alors plus au signe moins facultatif ou à un chiffre.


3

Cela fonctionnerait pour un format comme celui-ci: 31 ͦ 37.4 'E

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

1

Rubis

Longitude -179,99999999..180

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

Latitude -89,99999999..90

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

0

Une méthode complète et simple de l'objectif C pour vérifier la configuration correcte de la latitude et de la longitude est:

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

searchString est l'entrée que l'utilisateur entrerait dans le champ de texte respectif.


0

PHP

Voici la version de PHP (les valeurs d'entrée sont: $latitudeet $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

Vous pouvez essayer ceci:

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

Essaye ça:

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

-2

Essaye ça:

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

5
Les réponses en code pur sont rarement une bonne idée. Veuillez ajouter un texte descriptif à votre réponse.
timclutton

fonctionne très bien: valide avec précision et sélectionne lat, long de tout texte environnant. Cependant, ne limite pas le nombre de chiffres significatifs autorisés après la virgule décimale.
user4325241
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.