Eşleşen enlem / boylam koordinatları için normal ifade?


153

Enlem / boylam koordinatlarını eşleştirmek için normal bir ifade oluşturmaya çalışıyorum. Çift duyarlıklı bir sayıyı eşleştirmek için kullandım (\-?\d+(\.\d+)?)ve bunu tek bir ifadede birleştirmeye çalıştım:

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

Bunun bir çift, bir virgül, belki biraz boşluk ve başka bir çiftle eşleşmesini bekliyordum, ama işe yaramıyor gibi görünüyor. Spesifik olarak, yalnızca boşluk yoksa, bir veya daha fazla değilse çalışır. Neyi yanlış yaptım?

Yanıtlar:


119

Boşluk \ s, \ w değil

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

Bunun işe yarayıp yaramadığını görün


1
Virgül yerine nokta kullanmak zorunda kaldım: / ^(\-?\d+(\.\d+)?) HereAdot. endMod \ s * (\ -? \ d + (\. \ d +)?) $ /
kolodi

Enlemler ve uzunlar için izin verilen aralığın dışındaki değerleri kabul eder. ör. 91.181
Arun Karunagath

Bu, öngörülen uzamsal referans sistemlerinin x / y koordinatları için de
işe yarar

226

Bu, doğru aralığa düşen enlem ve boylam değerleriyle tam olarak eşleşecektir:

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

Maçlar

  • +90.0, -127.554334
  • 45, 180
  • -90, -180
  • -90.000, -180.0000
  • +90, +180
  • 47.1231231, 179.99999999

Eşleşmiyor

  • -90., -180.
  • +90.1, -100.111
  • -91, 123.456
  • 045, 180

Bu harika. Aralık kontrolünün dahil edilmesi için tebrikler.
radj

1
İlk eşleşme örneğinizde bir yazım hatası olduğunu düşünüyorum. RegEx'in 3 değerle eşleşeceğinden şüpheliyim.
Burkhard

Sabit. İki ayrı örnek olması gerekiyordu.
Iain Fraser

7
Virgülün her iki tarafında boşluk kabul edecek şekilde değiştirildi: ^ [- +]? ([1-8]? \ D (\. \ D +)? | 90 (\. 0 +)?) \ S *, \ s * [- +]? (180 (\. 0 +)? | ((1 [0-7] \ d) | ([1-9]? \ d)) (\. \ d +)?) $
puddinman13

2
Bunu, ?:yakalamayan grup sözdizimini kullanarak yakalama gruplarında sadece o lat lon'u elde etmek için değiştirdim ve polariteyi yakala(^[-+]?(?:[1-8]?\d(?:\.\d+)?|90(?:\.0+)?)),\s*([-+]?(?:180(?:\.0+)?|(?:(?:1[0-7]\d)|(?:[1-9]?\d))(?:\.\d+)?))$
narthur157

116

Bunları kullanıyorum (6 ondalık basamaklı ondalık biçim):

Enlem

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

Latitude Normal ifade görselleştirme

Boylam

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

Boylam Normal ifade görselleştirme


Burada erişim kolaylığı açısından her ikisini de test eden bir özet var. Bu bir Java TestNG testi. Çalıştırmak için Slf4j, Hamcrest ve Lombok'a ihtiyacınız var:

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

Bu gerçekten güzel bir normal ifadeydi! Ama biraz kısaltmak mümkün mü? :)
Yapamazsa

@ErikEdgren Kısaltmanın bir yolunu bulamadım :(
Marco Ferrari

2
Tamam: / Oh güzel.
Normal ifadeniz

2
güzel görsel: D Bu web sitesini bilmiyordum! Teşekkür ederim !
Damiii

Web sitesi url'si nedir
basickarl

19

Aslında Alix Axel, yukarıdaki regex enlem, boylam aralıkları açısından yanlıştır.

Enlem ölçümleri –90 ° ile + 90 ° arasındadır Boylam ölçümleri –180 ° ile + 180 ° arasındadır

Dolayısıyla, aşağıda verilen normal ifade daha doğru bir şekilde geçer.
Ayrıca benim düşünceme göre hiç kimse ondalık noktayı enlem / boylam olarak sınırlamamalı.

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

VEYA Amaç C için

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

2
Bu kabul 99için Latitudeise, 99kapsama alanı dışında olduğunu -90, +90ve bu nedenle geçersiz.
ako

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

Normal ifade dökümü:

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

-? # negatif değerleri kabul et

^ # Dize başlangıcı

[0-9]{1,3} # 1-3 basamakla eşleştir (ör. 0-999)

(?: # Eşleştirmeye çalışın ...

\. # ondalık nokta

[0-9]{1,10} # ardından 1-10 basamak (ör. 0-9999999999)

)? # ... isteğe bağlı olarak

$ # Dizenin sonu


Bence seninki en zarif. İlk olarak, kaçış karakterlerini düzenlemek ve değiştirmek zorunda kalmadan hemen çalıştı. İkincisi, kısadır. Üçüncüsü, anlaşılması kolaydır.
Jim Rota

9

Bunu dene:

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

Şuraya göz atın:

http://regexpal.com/

İfadeyi üst kutuya yapıştırın, ardından aşağıdaki gibi şeyleri alttaki kutuya yerleştirin:

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

Normal ifade dökümü:

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

Şimdi, bunun yapmadığı şey, kendisini bu aralıkla sınırlamaktır:

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

Bunun yerine, kendisini bu aralıkla sınırlar:

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

Ancak asıl mesele sadece ifadenin her bir parçasını parçalamaktır.


7

İşte daha katı bir versiyon:

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

1
Bence önce {1,2} gelmeli, sonra {1,3}
randunel

@Arjan: Düzeltildi, hep ikisini karıştırıyorum. Teşekkürler!
Alix Axel

5

Python:

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

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

Latitude, örnekte başarısız olmalıdır.


4

@ macro-ferrari Bunu kısaltmanın bir yolunu buldum ve regex motorları hakkındaki tüm son konuşmaların ışığında önden bakmadan

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

görüntü açıklamasını buraya girin

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

görüntü açıklamasını buraya girin


Güzel açıklama, bu akış kontrolünü kullandığınız herhangi bir özel yazılımı nasıl elde ettiniz? bu bir regexper.com mu?
sessizsudo

3

\ S (boşluk) kullanmanız gereken yerde \ w (kelime karakteri) kullandığınıza inanıyorum. Kelime karakterleri tipik olarak [A-Za-z0-9_] 'dan oluşur, böylece alanınız hariç tutulur ve daha sonra isteğe bağlı eksi işareti veya bir rakamda eşleşme başarısız olur.


3

Bu, şu şekilde bir format için işe yarar: 31 ͦ 37.4 'E

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

1

Yakut

Boylam -179.99999999..180

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

Enlem -89.99999999..90

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

0

Enlem ve boylam için doğru düzeni kontrol etmek için C hedefinde eksiksiz ve basit bir yöntem şudur:

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

burada searchedString , kullanıcının ilgili metin alanına gireceği girdidir.


0

PHP

İşte PHP'nin sürümü (giriş değerleri: $latitudeve $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

Bunu deneyebilirsiniz:

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

Bunu dene:

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

-2

Bunu dene:

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

5
Saf kod yanıtları nadiren iyi bir fikirdir. Lütfen cevabınıza açıklayıcı bir metin ekleyin.
timclutton

harika çalışıyor: doğru şekilde doğrular ve çevreleyen herhangi bir metinden enlem, uzun süreyi seçer. Bununla birlikte, ondalık noktadan sonra izin verdiği önemli basamakların sayısını sınırlamaz.
user4325241
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.