具有可选匹配的Ruby Regex

时间:2017-04-16 22:32:44

标签: ruby regex match optional

以下是我匹配的文字

AQUEDUCT - March 25, 2017 - Race 4\n MAIDEN CLAIMING - Thoroughbred\n 
INNER DIRT FOR MAIDENS, FOUR YEARS OLD AND UPWARD FOALED IN NEW YORK STATE AND 
APPROVED BY THE\n NEW YORK STATE-BRED REGISTRY. Weight, 121 lbs. Claiming 
Price $25,000. (S) Claiming Price: $25,000\n Six Furlongs On The Inner track 
Track Record: (Captain Red - 1:07.93 - February 26, 2003)\n Purse:

这个正则表达式失败了,即使可选的claiming_price子句前面有非贪婪的"。*?"序列。

/(Thoroughbred).*?(?<claiming_price>Claiming Price:.*?\n)?.*Track Record:/m

当我拿出&#34;?&#34;在claiming_price子句之后,它可以正常工作

/(Thoroughbred).*?(?<claiming_price>Claiming Price:.*?\n).*Track Record:/m

当claiming_price子句是可选匹配时,为什么它不起作用?如何使其匹配并使claiming_price子句可选?

编辑:我如何使这个更复杂的正则表达式工作?这是我实际使用的那个。我在原帖中进行了简化,使读者更容易阅读。但我正在处理你的回答,而且我不确定如何将它应用到我的真正的正则表达式。

/(Thoroughbred|Quarter Horse)\n(?<rules>.*?)(?<claiming_price>Claiming Price:.*?\n)?(?<track_type>(?:(?!\n).)*?)Track Record:.*? - (?<track_record>\d.*?\d) -.*\nPurse/m

1 个答案:

答案 0 :(得分:2)

不要在声明价格捕获组中使用?量词(即保持强制性,仅匹配一次)并将其与.*?包裹在一起< em>在它之前在可选的非捕获组中:

/(Thoroughbred)(?:.*?(?<claiming_price>Claiming Price:.*?\n))?.*Track Record:/m
               ^^                                           ^^

请参阅Rubular demo

现在,它会像这样工作:

  • (Thoroughbred) - Thoroughbred substring
  • (?:.*?(?<claiming_price>Claiming Price:.*?\n))? - 一次或零次(?)次出现:
    • .*? - 在第一次出现的后续子模式之前尽可能少的0个字符
    • (?<claiming_price>Claiming Price:.*?\n) - claiming_price 群组捕获
      • Claiming Price: - Claiming Price: substring
      • .*?\n - 任意0个字符尽可能少,直到第一个换行符
  • .* - 在最后一次出现
  • 之前尽可能多的0个字符
  • Track Record: - Track Record:字符串。

为什么它不适用于您的第一个正则表达式?

(Thoroughbred)匹配Thoroughbred。然后,首先跳过.*?模式,进行了懒惰量化,并尝试了(?<claiming_price>Claiming Price:.*?\n)?。由于Claiming Price:之后缺少Thoroughbred,因此使用?量化的模式匹配空字符串(因为?量词可以匹配1或0个此类模式序列)。然后,.*Track Record:抓住了剩余的匹配(任意0个字符,直到最后一次出现Track Record:)。