0

我想我很擅长正则表达式,但是这个让我很难过。我正在尝试匹配国家气象局预报公告中使用的某种语言。我在 Windows 上使用 Perl 5.16。我还使用这个在线正则表达式测试器进行了测试。这是一个示例消息:

...A SEVERE THUNDERSTORM WARNING REMAINS IN EFFECT UNTIL 1130 PM CST FOR CENTRAL LAMAR COUNTY... AT 1106 PM CST...NATIONAL WEATHER SERVICE METEOROLOGISTS WERE TRACKING A SEVERE THUNDERSTORM CAPABLE OF PRODUCING PING PONG BALL SIZE HAIL...AND DESTRUCTIVE WINDS IN EXCESS OF 70 MPH. THIS STORM WAS LOCATED NEAR BAXTERVILLE MOVING EAST AT 50 MPH. THE SEVERE THUNDERSTORM WILL BE NEAR... PURVIS BY 1115 PM CST... WEST HATTIESBURG BY 1120 PM CST...

这是我的正则表达式:

/A SEVERE THUNDERSTORM.+?(?<hsize>QUARTER|GOLF BALL|PING PONG BALL|HALF DOLLAR)?.+?WINDS (?:IN EXCESS OF|OVER) (?<wmph>\d+) MPH.+WAS LOCATED (?:(?<dist>\d+) MILES (?<dir>\w+) OF|(?<near>NEAR)) (?<loc>[\w ]+).+MOVING (?<mdir>\w+) AT (?<mph>\d+) MPH/

问题是hsize参数总是返回空白。我希望它是可选的但很贪婪,但它永远不会匹配。我尝试将其设为非可选:

/A SEVERE THUNDERSTORM.+?(?<hsize>QUARTER|GOLF BALL|PING PONG BALL|HALF DOLLAR).+?WINDS (?:IN EXCESS OF|OVER) (?<wmph>\d+) MPH.+WAS LOCATED (?:(?<dist>\d+) MILES (?<dir>\w+) OF|(?<near>NEAR)) (?<loc>[\w ]+).+MOVING (?<mdir>\w+) AT (?<mph>\d+) MPH/

这确实导致它匹配,这对我来说毫无意义。如您所见,我已经使通配符不贪婪,所以我看不到发生了什么。

4

2 回答 2

5

您可以更改一些正则表达式以强制引擎在匹配任何内容之前搜索特殊文本。更改正则表达式的这一部分:

.+?(?<hsize>QUARTER|GOLF BALL|PING PONG BALL|HALF DOLLAR)?

到:

(?:.+?(?<hsize>QUARTER|GOLF BALL|PING PONG BALL|HALF DOLLAR)|.+?)

交替将迫使引擎在继续匹配任何内容(第二个选项)之前用尽所有找到与特殊关键字匹配的可能性(第一个选项)。

于 2013-02-11T05:53:19.757 回答
4
/A SEVERE THUNDERSTORM.+?(?<hsize>QUARTER|GOLF BALL|PING PONG BALL|HALF DOLLAR)?.+?WINDS/

我相信匹配是这样的:

  1. 找到"A SEVERE THUNDERSTORM"
  2. 首先匹配.+?:第一次尝试使用空字符串。
  3. Match (?<hsize>...)?:从这个位置开始,它只能匹配一个空字符串。
  4. 匹配第二个.+?:第一次尝试使用空字符串。
  5. 匹配失败"WINDS"。回到第 4 步。
  6. 多次回溯,最终第二个.+?匹配整个字符串 fromTHUNDERSTORM到 next WINDS

所以回溯永远不会回到第 3 步或第 2 步。

也许您可以捕获 and 之间的所有文本THUNDERSTORMWINDS稍后在其上运行单独的正则表达式,或者将一个或两个更改.+?为与冰雹大小描述不匹配的内容。

于 2013-02-11T05:42:30.527 回答