นิพจน์ปกติสำหรับพิกัดละติจูด / ลองจิจูดที่ตรงกันหรือไม่


149

ฉันพยายามสร้างนิพจน์ทั่วไปสำหรับการจับคู่พิกัดละติจูด / ลองจิจูด สำหรับการจับคู่ตัวเลขที่มีความแม่นยำสองเท่าที่ฉันเคยใช้(\-?\d+(\.\d+)?)และพยายามที่จะรวมเข้าด้วยกันในนิพจน์เดียว:

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

ฉันคาดว่าสิ่งนี้จะจับคู่หนึ่งคู่เครื่องหมายจุลภาคบางทีพื้นที่และอีกสองเท่า แต่ดูเหมือนจะไม่ทำงาน โดยเฉพาะจะใช้งานได้หากไม่มีที่ว่างไม่ใช่อย่างน้อยหนึ่งรายการ ฉันทำอะไรผิด

คำตอบ:


117

ช่องว่างคือ \ s ไม่ใช่ \ w

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

ดูว่ามันใช้ได้ไหม


1
ฉันต้องใช้จุดแทนเครื่องหมายจุลภาค: /^(\-?\d+(\.\d+)?) ที่นี่มาก endMod \ s * (\ -? \ d + (\. \ d +)?) $ /
kolodi

ยอมรับค่านอกช่วงที่อนุญาตสำหรับ lats และ longs เช่น 91,181
Arun Karunagath

ใช้งานได้กับ x / y- พิกัดของระบบอ้างอิงเชิงพื้นที่ที่คาดการณ์ไว้เช่นกัน
DeEgge

218

ค่านี้จะจับคู่ค่าละติจูดและลองจิจูดอย่างเคร่งครัดซึ่งอยู่ในช่วงที่ถูกต้อง:

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

ไม้ขีด

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

ไม่ตรงกัน

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

นี่มันเจ๋งมาก. ความรุ่งโรจน์สำหรับการตรวจสอบรวมช่วง
radj

1
ฉันคิดว่าคุณมีการพิมพ์ผิดในตัวอย่างการแข่งขันครั้งแรกของคุณ ฉันสงสัยว่า RegEx จะจับคู่ 3 ค่า
Burkhard

แก้ไขแล้ว. มันควรจะเป็นสองตัวอย่างที่แยกจากกัน
เฟนเฟรเซอร์

7
แก้ไขเพื่อยอมรับ white-space ทั้งสองด้านของเครื่องหมายจุลภาค: ^ [- +]? ([1-8]? \ d (\. \ d +)? | 90 (\. 0 +)?) \ s *, \ s * [- +]? (180 (\. 0 +)? | ((1 [0-7] \ d) | ([1-9]? \ d)) (\. \ d +)? $
puddinman13

2
ฉันเปลี่ยนสิ่งนี้เพื่อรับ lat lon นั้นในกลุ่มการจับภาพโดยใช้?:ไวยากรณ์กลุ่มที่ไม่จับภาพรวมถึงการจับขั้ว(^[-+]?(?:[1-8]?\d(?:\.\d+)?|90(?:\.0+)?)),\s*([-+]?(?:180(?:\.0+)?|(?:(?:1[0-7]\d)|(?:[1-9]?\d))(?:\.\d+)?))$
narthur157

109

ฉันใช้สิ่งเหล่านี้ (รูปแบบทศนิยมโดยมีทศนิยม 6 หลัก):

ละติจูด

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

การสร้างภาพข้อมูลนิพจน์ทั่วไปของ Latitude

ลองจิจูด

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

ลองจิจูดการสร้างภาพการแสดงออกปกติ


นี่คือส่วนสำคัญที่ทดสอบทั้งสองรายงานที่นี่ด้วยเพื่อความสะดวกในการเข้าถึง เป็นการทดสอบ Java TestNG คุณต้องการ Slf4j, Hamcrest และ Lombok เพื่อเรียกใช้:

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

นี่เป็น regex ที่ดีจริงๆ! แต่เป็นไปได้ไหมที่จะย่อให้สั้นลงหน่อย? :) ถ้ามันไม่ได้เป็นของรหัสดีแล้ว แต่ร่นยินดีต้อนรับเสมอ :)
Airikr

@ErikEdgren ฉันไม่พบวิธีที่จะย่อให้สั้นลง :(
Marco Ferrari

1
ตกลง: / โอ้ดี regex ของคุณยังยอดเยี่ยม;)
Airikr

2
ภาพที่ดี: D ไม่รู้เกี่ยวกับเว็บไซต์นี้! ขอบคุณ !
Damiii


19

จริง ๆ แล้ว Alix Axel เหนือ regex ผิดในละติจูดลองจิจูดช่วงมุมมอง

การวัดละติจูดนั้นอยู่ระหว่าง –90 °ถึง + 90 °ลองจิจูดการวัดนั้นมีตั้งแต่ –180 °ถึง + 180 °

ดังนั้น regex ที่ระบุด้านล่างตรวจสอบความถูกต้องมากขึ้น
นอกจากนี้ตามความคิดของฉันไม่มีใครควร จำกัด จุดทศนิยมในละติจูด / ลองจิจูด

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

หรือสำหรับวัตถุประสงค์ C

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

2
มันรับ99สำหรับLatitudeในขณะที่99อยู่นอกช่วงของ-90, +90และไม่ถูกต้องดังนั้น
ako

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

การแยก Regex:

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

-? # ยอมรับค่าลบ

^ # เริ่มต้นของสตริง

[0-9]{1,3} # จับคู่ 1-3 หลัก (เช่น 0-999)

(?: # พยายามจับคู่ ...

\. # จุดทศนิยม

[0-9]{1,10} # ตามด้วยหนึ่งถึง 10 หลัก (เช่น 0-9999999999)

)? # ... ทางเลือก

$ # จุดสิ้นสุดของสตริง


ฉันคิดว่าคุณเป็นคนที่สง่างามที่สุด ประการแรกมันทำงานได้ทันทีโดยไม่ต้องแก้ไขและแทนที่อักขระเลี่ยง ประการที่สองมันสั้น ประการที่สามมันง่ายที่จะเข้าใจ
Jim Rota

9

ลองสิ่งนี้:

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

ตรวจสอบได้ที่:

http://regexpal.com/

วางนิพจน์ในกล่องด้านบนจากนั้นใส่สิ่งต่างๆลงในกล่องด้านล่าง:

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

การแยก 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).

ตอนนี้สิ่งนี้ไม่ได้ทำคือ จำกัด ตัวเองในช่วงนี้:

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

แต่มัน จำกัด ตัวเองไว้ที่ช่วงนี้:

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

แต่ประเด็นสำคัญคือการแยกแยะการแสดงออกแต่ละชิ้น


7

นี่คือรุ่นที่เข้มงวดมากขึ้น:

^([-+]?\d{1,2}[.]\d+),\s*([-+]?\d{1,3}[.]\d+)$
  • ละติจูด = -90-+90
  • ลองจิจูด = -180-+180

1
ฉันเชื่อว่า {1,2} ควรมาก่อนจากนั้น {1,3}
randunel

@Arjan: แก้ไขฉันมักจะสับสนทั้งสอง ขอบคุณ!
Alix Axel

5

งูหลาม:

ละติจูด: result = re.match("^[+-]?((90\.?0*$)|(([0-8]?[0-9])\.?[0-9]*$))", '-90.00001')

ลองจิจูด: result = re.match("^[+-]?((180\.?0*$)|(((1[0-7][0-9])|([0-9]{0,2}))\.?[0-9]*$))", '-0.0000')

ละติจูดควรล้มเหลวในตัวอย่าง


4

@ macro-ferrariฉันหาทางย่อให้สั้นลงและไม่ต้องมองไปที่แสงเมื่อพูดถึงล่าสุดเกี่ยวกับเอนจิ้นของ regex

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

ป้อนคำอธิบายรูปภาพที่นี่

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

ป้อนคำอธิบายรูปภาพที่นี่


คำอธิบายที่ดี btw คุณได้รับการควบคุมการไหลของซอฟต์แวร์เฉพาะใด ๆ ที่คุณใช้ regexper.comอันนี้หรือ
silentsudo

3

ฉันเชื่อว่าคุณกำลังใช้ \ w (ตัวอักษรคำ) ที่คุณควรใช้ \ s (ช่องว่าง) โดยทั่วไปแล้วตัวอักษรของ Word ประกอบด้วย [A-Za-z0-9_] ดังนั้นจึงไม่รวมช่องว่างของคุณซึ่งต่อไปจะไม่สามารถจับคู่กับเครื่องหมายลบหรือตัวเลือกเพิ่มเติมได้


3

สิ่งนี้จะทำงานในรูปแบบดังนี้: 31 ͦ 37.4 'E

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

1

ทับทิม

ลองจิจูด-179.99999999..180

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

ละติจูด-89.99999999..90

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

0

วิธีการที่สมบูรณ์และเรียบง่ายในวัตถุประสงค์ C สำหรับการตรวจสอบรูปแบบที่ถูกต้องสำหรับละติจูดและลองจิจูดคือ:

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

โดยที่สืบค้นStringเป็นอินพุตที่ผู้ใช้ป้อนในฟิลด์ข้อความที่เกี่ยวข้อง


0

PHP

นี่คือเวอร์ชันของ PHP (ค่าอินพุตคือ: $latitudeและ$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

คุณสามารถลองสิ่งนี้:

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

ลองสิ่งนี้:

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

5
คำตอบของรหัสบริสุทธิ์มักเป็นความคิดที่ดี โปรดเพิ่มข้อความอธิบายลงในคำตอบของคุณ
timclutton

ใช้งานได้ดี: ตรวจสอบความถูกต้องได้อย่างแม่นยำและแยก lat จากข้อความที่อยู่รอบ ๆ อย่างไรก็ตามไม่ จำกัด จำนวนของตัวเลขนัยสำคัญที่อนุญาตให้ใช้หลังจุดทศนิยม
user4325241
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.