正则表达式匹配许多坐标格式

时间:2018-01-09 22:16:36

标签: regex string-matching

我正在开发一个匹配许多不同类型的位置坐标的正则表达式。到目前为止,它匹配了大约90%的格式:

([SNsn][\\s]*)?((?:[\\+-]?[0-9]*[\\.,][0-9]+)|(?:[\\+-]?[0-9]+))(?:(?:[^ms'′""″,\\.\\dNEWnew]?)|(?:[^ms'′""″,\\.\\dNEWnew]+((?:[\\+-]?[0-9]*[\\.,][0-9]+)|(?:[\\+-]?[0-9]+))(?:(?:[^ds°""″,\\.\\dNEWnew]?)|(?:[^ds°""″,\\.\\dNEWnew]+((?:[\\+-]?[0-9]*[\\.,][0-9]+)|(?:[\\+-]?[0-9]+))[^dm°'′,\\.\\dNEWnew]*))))([SNsn]?)[^\\dSNsnEWew]+([EWew][\\s]*)?((?:[\\+-]?[0-9]*[\\.,][0-9]+)|(?:[\\+-]?[0-9]+))(?:(?:[^ms'′""″,\\.\\dNEWnew]?)|(?:[^ms'′""″,\\.\\dNEWnew]+((?:[\\+-]?[0-9]*[\\.,][0-9]+)|(?:[\\+-]?[0-9]+))(?:(?:[^ds°""″,\\.\\dNEWnew]?)|(?:[^ds°""″,\\.\\dNEWnew]+((?:[\\+-]?[0-9]*[\\.,][0-9]+)|(?:[\\+-]?[0-9]+))[^dm°'′,\\.\\dNEWnew]*))))([EWew]?)

测试格式:

  

N 45°55.732 W 122°29.882

     

N 047°38.938',W 122°20.887'

     

40.123,-74.123

     

40.123°N 74.123°W

     

40°7'22.8“N 74°7'22.8”W

     

40°7.38', - 74°7.38'

     

N40°7'22.8,W74°7'22.8“

     

40°7'22.8“N,74°7'22.8”W

     

40 7 22.8,-74 7 22.8

     

40.123 -74.123

     

40.123°,-74.123°

     

144442800,-266842800

     

40.123N74.123W

     

4007.38N7407.38W

     

40°7'22.8“N,74°7'22.8”W

     

400722.8N740722.8W

     

N 40 7.38 W 74 7.38

     

40:7:23N,74:7:23W

     

40:7:22.8N 74:7:22.8W

     

40°7'23“N 74°7'23”W

     

40°7'23“-74°7'23”

     

40d 7'23“N 74d 7'23”W

     

40.123N 74.123W

     

40°7.38,-74°7.38

测试是否有效:https://regexr.com/3ivu2

enter image description here

正如您所看到的,空格和逗号存在问题导致正则表达式与某些格式不匹配。

我正在尝试匹配坐标字符串,以便可以在我的iOS应用中突出显示它们,并允许用户点按它们。

如何更新正则表达式并修复匹配问题?

2 个答案:

答案 0 :(得分:0)

概述

我确信有很多方法可以解决这个问题。由于您尚未指定正则表达式引擎或编程语言,因此我将发布一个适用于PCRE的内容以及在大多数引擎中应该起作用的内容。 PCRE正则表达式比非PCRE正则表达式更容易理解,但两者都使用完全相同的逻辑。

下面定义的模式与您在问题中呈现的每个字符串相匹配,并正确地分隔坐标(x,y)的每个部分。

代码

PCRE

此方法使用DEFINE构造来预定义模式。这种结构的优点在于,您可以在一个位置定义正则表达式的可重用部分,因此,您只需编辑这些子模式即可编辑大多数正则表达式。

See regex in use here

(?(DEFINE)
  (?<ns>[ns])
  (?<ew>[ew])
  (?<d>[°´’'"d:])
  (?<n>[+-]?\d+(?:\.\d+)?)
)
(
  (?&ns)?
  (?:\ ?(?&n)(?&d)?){1,3}
  \ ?(?&ns)?
)
\ ?,?\ ?
(
  (?&ew)?
  (?:\ ?(?&n)(?&d)?){1,3}
  \ ?(?&ew)?
)

标志:gix

非PCRE

See regex in use here

(
  [ns]?
  (?:\ ?[+-]?\d+(?:\.\d+)?[°´’'"d:]?){1,3}
  \ ?[ns]?
)
\ ?,?\ ?
(
  [ew]?
  (?:\ ?[+-]?\d+(?:\.\d+)?[°´’'"d:]?){1,3}
  \ ?[ew]?
)

标志:gix

某些引擎没有x标志。对于那些引擎,您可以使用以下单行(as seen here):

([ns]?(?: ?[+-]?\d+(?:\.\d+)?[°´’'"d:]?){1,3} ?[ns]?) ?,? ?([ew]?(?: ?[+-]?\d+(?:\.\d+)?[°´’'"d:]?){1,3} ?[ew]?)

说明

由于两种模式基本相同(非PCRE只是PCRE的扩展版本),我将定义PCRE正则表达式模式,因为它更容易掌握。

请注意,使用x的模式已转义空格,因为它们会被忽略(x忽略模式中的空格)。 i标志允许我们匹配文本而不管大小写(i使我们的模式不区分大小写)。

定义

  • (?(DEFINE)...)正则表达式完全忽略DEFINE组。它被视为var name=value,而您可以通过其名称来回忆使用的特定模式。
  • (?<ns>[ns])群组ns匹配集nsNS
  • 中的任何字符
  • (?<ew>[ew])群组ew匹配集ewEW
  • 中的任何字符
  • (?<d>[°´’'"d:])群组d匹配集°´’'"d:
  • 中的任何字符
  • (?<n>[+-]?\d+(?:\.\d+)?)n匹配与以下结构匹配的任何数字
    • [+-]?可选择匹配集+-
    • 中的任何字符
    • \d+匹配一个或多个数字
    • (?:\.\d+)?可选择匹配小数点后跟一个或多个数字

模式

图案由3个较大的部分组成。第一个和最后一个是捕获组(坐标本身),第二个是将两者分开的。

  • 捕获1:
    • (?&ns)?可选择匹配论坛ns
    • (?:\ ?(?&n)(?&d)?){1,3}匹配[可选空格,然后是群组n,然后可选地将群组d]匹配一到三次
    • \ ?(?&ns)?(可选)匹配空格,可选择匹配组ns
  • \ ?,?\ ?匹配可选空格,逗号和空格(这将分隔每个坐标部分)
  • 捕获2:这与 Capture 1 相同,但将组ns替换为组ew

答案 1 :(得分:0)

这个简化的正则表达式字面上匹配了您给出的所有模式:

^((?:[NW]? ?(?:[-\d.d]+[NW:°´’'",]?[ NW]?)+[, ]*)+[NW]?)$

我不是坐标专家,但如果我没有考虑到某些细节,你可以轻松修改它。

完整测试为here