【问题标题】:Python Regular Expression: Matching Car Speeds without Highway NamesPython 正则表达式:匹配没有高速公路名称的车速
【发布时间】:2016-11-04 09:54:00
【问题描述】:

我正在尝试匹配高速公路票的速度描述,例如,文本行:

“L A 16-25MPH”应返回 2 组:16、25
“LMT ACC 6-10”应返回 2 组:6、10
“6 OVER”应返回 1 组:6

我对上述所有情况都很好,但我遇到了与速度无关的数字字符串的问题,例如:

“LIMITED ACCESS SPEED I-75”应该不返回任何匹配项。
我可以捕获所有需要的最接近的表达式是:((?<!\w-)\d+)[^\d]*((?<!\w-)\d+)?,它将匹配 1 个组:5,使用 python 正则表达式引擎

现在,可以安全地假设一个字母然后一个连字符 (\w-) 是我试图使用负回溯排除的内容,我只是不确定如何分组多个数字(@ 987654324@) 使用负回溯。

【问题讨论】:

标签: python regex python-2.7


【解决方案1】:

说明

([0-9]+)(?:-([0-9]+)|\s*over)

** 要更好地查看图像,只需右键单击图像并选择在新窗口中查看

此正则表达式将执行以下操作:

  • 匹配与速度相关的数字
  • 避免使用道路名称中的数字

示例

现场演示

https://regex101.com/r/hE5dL4/2

示例文本

注意:关于I-75的边缘情况

'm trying to match speed descriptions of highway tickets, for example,text lines:

"L A 16-25MPH" should return 2 groups: 16, 25 
"LIMITED ACCESS SPEED I-75" should return no matches.
"LMT ACC 6-10" should return 2 groups: 6, 10 
"6 OVER" should return 1 group: 6

I'm OK with all of the above situations, but I run into issues for strings with numbers that aren't related to speed, for example:

"LIMITED ACCESS SPEED I-75" should return no matches.

示例匹配

MATCH 1
1.  [89-90] `16`
2.  [91-93] `25`

MATCH 2
1.  [193-194]   `6`
2.  [195-197]   `10`

MATCH 3
1.  [231-232]   `6`

说明

NODE                     EXPLANATION
----------------------------------------------------------------------
  (                        group and capture to \1:
----------------------------------------------------------------------
    [0-9]+                   any character of: '0' to '9' (1 or more
                             times (matching the most amount
                             possible))
----------------------------------------------------------------------
  )                        end of \1
----------------------------------------------------------------------
  (?:                      group, but do not capture:
----------------------------------------------------------------------
    -                        '-'
----------------------------------------------------------------------
    (                        group and capture to \2:
----------------------------------------------------------------------
      [0-9]+                   any character of: '0' to '9' (1 or
                               more times (matching the most amount
                               possible))
----------------------------------------------------------------------
    )                        end of \2
----------------------------------------------------------------------
   |                        OR
----------------------------------------------------------------------
    \s*                      whitespace (\n, \r, \t, \f, and " ") (0
                             or more times (matching the most amount
                             possible))
----------------------------------------------------------------------
    over                     'over'
----------------------------------------------------------------------
  )                        end of grouping
----------------------------------------------------------------------

【讨论】:

  • 我认为这非常接近,但是您的现场演示中的前 16 个仅捕获了 6 个。我尝试稍微修改一下: (\d+)(?:-(\d+)|\s*over) 这似乎有效。如果您看到任何主要流量,请告诉我。另外,谢谢你的帮助:)
  • 六个来自字符串"6 OVER" should return 1 group: 6,其中没有其他数字可以匹配。
  • 我可能弄错了,但是对于 match1,它匹配 6 和 25,但应该是 16 和 25。也许我遗漏了一些东西,因为我对正则表达式很陌生-但我看不到任何其他阅读方式。
  • 哦,我明白你在说什么了,是的,我写的 ([0-9])+ 是错误的。应该是([0-9]+)。在旁注中,我看到您正在使用 \d 字符类。我建议不要使用它,因为它的效率不如[0-9]
  • 太好了,行得通!感谢您提供有关 \d 字符类的建议!
【解决方案2】:

负后视必须是固定长度(有关详细信息,请参阅Python doc),因此不允许使用\d+ 之类的内容。

不过,您可以使用后向检查来检查高速公路的某些固定宽度指示符,例如 IRT(不区分大小写)。您可能还想添加其他案例以在破折号周围添加一个空格,根本没有破折号等。

一个可能符合条件的选项(设置不敏感标志):(?<!i|rt)(\d+)

【讨论】:

    猜你喜欢
    • 2021-10-10
    • 2013-02-17
    • 1970-01-01
    • 2016-01-22
    • 1970-01-01
    • 1970-01-01
    • 2016-01-15
    • 1970-01-01
    • 2014-01-17
    相关资源
    最近更新 更多