hhmmss 中 +/-90 度边界上的天文偏角(纬度)的正则表达式

Regex for astronomical declination (latitude) on +/-90 degrees boundary in hhmmss

我试图确保正则表达式匹配模式适用于 -90 到 +90 度之间的所有天文偏角。

我正在使用如下匹配模式:

^(?:(?:[+-]?([0-8]?\d|2[0-9])[°:\s])\s?\s?([0-5]?\d)[\':\s]?)\s?([0-5]?\d).?([0-9]?\d{1,9})[\"]?$

我在这里添加了一些我希望失败和成功的字符串:

https://regex101.com/r/Z0Kf6I/1

我几乎明白了,但我正在努力如何允许以下我想要匹配但目前不匹配的字符串:

90°00'00.00" => Succeed, but failing
90:00:00.00 => Succeed, but failing
+90:00:00.00 => Succeed, but failing
-90:00:00.00 => Succeed, but failing
+90°00'00.00" => Succeed, but failing
-90°00'00.00" => Succeed, but failing
90 0 0.00 => Succeed, but failing

基本上,这是因为我匹配了下面列表中的单个字符 [0-8]。但是将其更改为 [0-9] 显然会允许大于 90 的值,例如 91,92 等,但这些应该会失败。

任何关于如何实现这一点的专业 Regex 技巧将不胜感激!

看来我可以用这个正则表达式更接近一点:

^(?:(?:[+-]?([0-8]?\d|90)[°:\s])\s?([0-5]?\d)[\':\s]?)\s?([0-5]?\d)\.(\d{1,9})[\"]?

我会单独处理正好是 90 的情况,如下所示:

^[+-]?(?:[0-8]\d|\d)[°: ]?\s*?\d\d?[': ]\s*?\d\d?\.\d+\"?|^[+-]?90[°: ]\s*?00?[': ]\s*?00?\.0+\"?

https://regex101.com/r/wByk9t/1

我会避免在正则表达式中解释数字,不一定是因为它不可能,而是因为它更难阅读和维护。您可以使用以下正则表达式进行匹配:

([+-]?\d+)([°: ])(\d+)([': ])(\d+[.]\d*)("?)

现在你可以把第1、3、5组转换成一个数字,然后检查它是否>90。你也可以检查第2、4、6组中的分隔符是否匹配。

你可以使用

^[+-]?([0-8]?\d|90(?=(?:\D*0)*\D*$))[°:\s]\s{0,2}([0-5]?\d)[':\s]?\s?([0-5]?\d).?(\d{1,10})\"?

参见regex demo

详情:

  • ^ - 字符串开头
  • [+-]? - 可选的 -+
  • ([0-8]?\d|90(?=(?:\D*0)*\D*$)) - 第 1 组:从 08 的可选数字,然后是任何一个数字,或 90 紧跟零次或多次重复任何 non-digit 个字符后跟一个 0 个字符,然后是任何 non-digit 个字符,直到字符串
  • 结束
  • [°:\s] - °: 或空格
  • \s{0,2} - 零、一或两个空格
  • ([0-5]?\d) - 第 2 组:从 05 范围内的一个可选数字,然后是一个数字
  • [':\s]? - 可选的 ': 和空格
  • \s? - 一个可选的空格
  • ([0-5]?\d) - 第 3 组:从 05 范围内的一个可选数字,然后是一个数字
  • .? - 除换行符以外的任何可选字符
  • (\d{1,10}) - 第 4 组:一到十位数字
  • \"? - 一个可选的 " 字符。

我的理解是 90 是最大值,所以如果第一个数字是 90 那么后面的任何数字都必须是零。在这种情况下,只需将 90 和全零情况设置为替代:

^(?:[+-]?(90)[°:\s]\s*(0+)[\':\s]?\s*(0+)\.(0+)[\"]?|[+-]?([0-8]?\d)[°:\s]\s*([0-5]?\d)[\':\s]?\s*([0-5]?\d)\.(\d+)[\"]?)

https://regex101.com/r/Z0Kf6I/4

经过一些解释,适用于带有 x 标志的 Perl or Python

^ # start of line
(?:
    [+-]?(90)[°:\s]        # 90 degrees with optional unit or separator
    \s*
    (0+)[\':\s]?           # 0 minutes with optional unit or separator
    \s*
    (0+)\.(0+)[\"]?        # 0.0 seconds with optional unit
| # OR
    [+-]?([0-8]?\d)[°:\s]  # 0-89 degrees with optional unit or separator
    \s*
    ([0-5]?\d)[\':\s]?     # 0-59 minutes with optional unit or separator
    \s*
    ([0-5]?\d)\.(\d+)[\"]? # 0-59 seconds with optional unit
)

但正如我在评论中所说,无论您使用何种语言,都可以更好地实现这一点。在可能的分隔符上拆分它,然后根据您的逻辑进行任何检查。比正则表达式更容易理解和维护代码。

我的尝试:

^[+-]?(90(?!.*[1-9])|[0-8]?[0-9]?)(?:°|:|\s)\s*(60(?!.*[1-9])|[0-5]?[0-9])(?:\'|:|\s)\s*([0-5]?[0-9]\.\d+)(?:\")?$

regex101 demo

它也不会匹配大于 60 的分钟,比如

89° 60' 59.99" => 其他失败案例

89° 60' 60.00" => 其他失败案例

89° 59' 60.01" => 其他失败案例