【问题标题】:Regular Expression to match many coordinate formats正则表达式匹配许多坐标格式
【发布时间】:2018-01-09 22:16:35
【问题描述】:

我正在研究一个匹配许多不同类型的位置坐标的正则表达式。到目前为止,它匹配了大约 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]?)

测试格式:

北纬 45° 55.732 西经 122° 29.882

北纬 047° 38.938',西经 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

北 40 7.38 西 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

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

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

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

【问题讨论】:

  • 您是要验证坐标还是捕获零件?
  • 您不需要使用反斜杠对 [] 方括号内的字符进行转义。您实际上是在有效字符列表中包含反斜杠。
  • 在您的正则表达式中,我没有看到任何匹配失败。我错过了吗?
  • 其中一些格式与其他格式完全不同,试图将它们与单个模式匹配是一种毫无意义的练习。如果我是你,我会为每种坐标格式想出多个简单的模式。
  • @CAustin 我的问题是我对正则表达式知之甚少,不知道该怎么做。 :(

标签: regex string-matching


【解决方案1】:

概述

我相信有很多方法可以解决这个问题。由于您没有指定正则表达式引擎或编程语言,我将发布一个在 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,而您可以通过其名称调用特定模式以供使用。
  • (?&lt;ns&gt;[ns])ns 匹配集合中的任何字符 nsNS
  • (?&lt;ew&gt;[ew])ew 匹配集合中的任何字符 ewEW
  • (?&lt;d&gt;[°´’'"d:])d 匹配集合中的任何字符 °´’'"d:
  • (?&lt;n&gt;[+-]?\d+(?:\.\d+)?)n 匹配任何符合以下结构的数字
    • [+-]? 可以选择匹配集合中的任何字符 +-
    • \d+ 匹配一位或多位数字
    • (?:\.\d+)? 可选匹配小数点后跟一位或多位数字

图案

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

  • 捕获 1:
    • (?&amp;ns)? 可选匹配组ns
    • (?:\ ?(?&amp;n)(?&amp;d)?){1,3} 匹配 [一个可选空格,后跟组 n 然后可选组 d] 一到三次
    • \ ?(?&amp;ns)? 可选匹配空格,可选匹配组ns
  • \ ?,?\ ? 匹配一个可选的空格、逗号和空格(这将每个坐标部分分开)
  • 捕获 2:这与 捕获 1 相同,但将组 ns 替换为组 ew

【讨论】:

    【解决方案2】:

    这个简化的正则表达式完全匹配您给出的所有模式:

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

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

    完整的测试是here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-07-17
      • 1970-01-01
      • 2011-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多