Ekspresi reguler untuk mencocokkan koordinat lintang / bujur?


149

Saya mencoba membuat ekspresi reguler untuk mencocokkan koordinat lintang / bujur. Untuk mencocokkan angka presisi ganda yang saya gunakan (\-?\d+(\.\d+)?), dan mencoba menggabungkannya menjadi satu ekspresi:

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

Saya berharap ini cocok dengan ganda, koma, mungkin beberapa ruang, dan dua lagi, tetapi tampaknya tidak berhasil. Khususnya itu hanya berfungsi jika tidak ada ruang, tidak satu atau lebih. Apa yang telah saya lakukan salah?

Jawaban:


117

Spasi adalah \ s, bukan \ w

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

Lihat apakah ini berfungsi


1
Saya harus menggunakan dot alih-alih koma: /^(\-?\d+(\.\d+)?) Di siniAdot. endMod \ s * (\ -? \ d + (\. \ d +)?) $ /
kolodi

Ini menerima nilai di luar rentang yang diizinkan untuk lat dan long. mis., 91.181
Arun Karunagath

Ini berfungsi untuk koordinat x / y dari sistem referensi spasial yang diproyeksikan juga
DeEgge

218

Yang ini akan benar-benar cocok dengan nilai lintang dan bujur yang berada dalam kisaran yang benar:

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

Cocok

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

Tidak cocok

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

Ini luar biasa. Kudos untuk inklusi jangkauan pemeriksaan.
radj

1
Saya pikir Anda memiliki salah ketik dalam contoh pertandingan pertama Anda. Saya ragu bahwa RegEx akan cocok dengan 3 nilai.
Burkhard

Tetap. Itu dimaksudkan sebagai dua contoh terpisah.
Iain Fraser

7
Dimodifikasi untuk menerima spasi putih di kedua sisi koma: ^ [- +]? ([1-8]? \ D (\. \ D +)? | 90 (\. 0 +)?) \ S *, \ s * [- +]? (180 (\. 0 +)? | ((1 [0-7] \ d) | ([1-9]? \ d)) (\. \ d +)?) $
puddinman13

2
Saya mengubah ini untuk mendapatkan lat lat itu di dalam grup penangkap dengan menggunakan ?:sintaksis grup yang tidak menangkap, serta menangkap polaritas(^[-+]?(?:[1-8]?\d(?:\.\d+)?|90(?:\.0+)?)),\s*([-+]?(?:180(?:\.0+)?|(?:(?:1[0-7]\d)|(?:[1-9]?\d))(?:\.\d+)?))$
narthur157

109

Saya menggunakan yang ini (format desimal, dengan 6 digit desimal):

Garis Lintang

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

Visualisasi ekspresi reguler Latitude

Garis bujur

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

Bujur Visualisasi ekspresi reguler


Berikut adalah intisari yang menguji keduanya, dilaporkan di sini juga, untuk kemudahan akses. Ini adalah tes Java TestNG. Anda perlu Slf4j, Hamcrest dan Lombok untuk menjalankannya:

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

Ini adalah regex yang sangat bagus! Tetapi apakah mungkin untuk mempersingkat sedikit? :) Jika tidak bisa, tidak apa-apa tapi kode yang lebih pendek selalu diterima :)
Airikr

@ErikEdgren Saya tidak menemukan cara untuk mempersingkat :(
Marco Ferrari

1
Ok: / Oh well. Regex Anda masih luar biasa;)
Airikr

2
nice visual: D Tidak tahu tentang situs web ini! Terima kasih !
Damiii

Apa url situs web
K - Keracunan dalam SO tumbuh.

19

Sebenarnya Alix Axel, regex di atas salah dalam garis lintang, titik pandang garis bujur.

Pengukuran garis lintang berkisar dari –90 ° hingga + 90 ° Pengukuran garis bujur berkisar dari –180 ° hingga + 180 °

Jadi regex yang diberikan di bawah ini memvalidasi lebih akurat.
Juga, sesuai pemikiran saya, tidak ada yang harus membatasi titik desimal dalam lintang / bujur.

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

ATAU untuk Tujuan C

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

2
Itu menerima 99untuk Latitude, sementara 99berada di luar jangkauan -90, +90dan tidak valid.
ako

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

Regex breakdown:

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

-? # menerima nilai negatif

^ # Mulai string

[0-9]{1,3} # Cocokkan 1-3 digit (yaitu 0-999)

(?: # Cobalah untuk mencocokkan ...

\. # titik desimal

[0-9]{1,10} # diikuti oleh satu hingga 10 digit (yaitu 0-9999999999)

)? # ... secara opsional

$ # Akhir string


Saya pikir milikmu adalah yang paling elegan. Pertama, itu bekerja segera tanpa harus mengedit dan mengganti karakter melarikan diri. Kedua, pendek. Ketiga, mudah dimengerti.
Jim Rota

9

Coba ini:

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

Lihat di:

http://regexpal.com/

Rekatkan ekspresi di kotak atas, lalu masukkan hal-hal seperti ini di kotak bawah:

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

Regex breakdown:

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

Sekarang, apa yang TIDAK dilakukan adalah membatasi diri pada kisaran ini:

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

Alih-alih, ini sederhana membatasi diri ke rentang ini:

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

Tetapi intinya adalah terutama untuk memecah setiap bagian dari ekspresi.


7

Ini versi yang lebih ketat:

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

1
Saya percaya bahwa {1,2} harus didahulukan, kemudian {1,3}
randunel

@ Arjan: Memperbaiki, saya selalu membingungkan keduanya. Terima kasih!
Alix Axel

5

Python:

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

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

Latitude seharusnya gagal dalam contoh.


4

@ macro-ferrari Saya memang menemukan cara untuk mempersingkat, dan tanpa melihat ke depan dalam terang semua pembicaraan terakhir tentang mesin regex

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

masukkan deskripsi gambar di sini

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

masukkan deskripsi gambar di sini


Penjelasan yang bagus, tapi bagaimana Anda bisa mengontrol aliran perangkat lunak tertentu yang Anda gunakan. ini regexper.com ?
silentsudo

3

Saya yakin Anda menggunakan \ w (karakter kata) di mana Anda seharusnya menggunakan \ s (spasi putih). Karakter kata biasanya terdiri dari [A-Za-z0-9_], sehingga mengecualikan ruang Anda, yang kemudian gagal mencocokkan dengan tanda minus opsional atau digit.


3

Ini akan berfungsi untuk format seperti ini: 31 ͦ 37,4 'E

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

1

Rubi

Garis bujur -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

Metode yang lengkap dan sederhana dalam tujuan C untuk memeriksa pola lintang dan bujur yang benar adalah:

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

di mana searchingString adalah input yang akan dimasukkan pengguna di bidang teks masing-masing.


0

PHP

Ini adalah versi PHP (nilai inputnya adalah: $latitudedan $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

Anda dapat mencoba ini:

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

Coba ini:

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

-2

Coba ini:

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

5
Jawaban kode murni jarang merupakan ide yang bagus. Silakan tambahkan beberapa teks deskriptif untuk jawaban Anda.
timclutton

berfungsi dengan baik: memvalidasi secara akurat, dan memilih lat, panjang dari teks di sekitarnya. Namun, tidak membatasi jumlah digit signifikan yang dimungkinkan setelah titik desimal.
user4325241
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.