正则表达式捕获直到第一次匹配

时间:2015-02-26 08:55:26

标签: regex

我的正则表达式字符串看起来像

您的订单#Q-111-111-1111。账单金额为100.50美元

如何提取订单号,即'#'之间的字符串。第一个'。'

问-111-111-1111

我试过了:

/#(.*[^.])[.].+?/

但它捕捉到最后一个点字符。我确定,我需要使用非贪婪的匹配,但我无法做到这一点。

3 个答案:

答案 0 :(得分:4)

您可以简单地使用以下正则表达式:

#(.*?)\.

* 贪婪 - 当您将?追加到.*时,它会让引擎尽可能频繁地重复前面的令牌,它会 lazy (ungreedy),并将匹配到第一个点。

为了演示它,我们举个例子:

  • #(.*)\.适用于#12-34.234-3.234。你好世界

    .*将首先匹配所有内容,直到字符串结尾(d字符),然后它将尝试匹配点,但它不存在,所以它将保持回溯直到它匹配4,然后找到点,匹配的字符串是#1234.2343.234

  • #(.*?)\.适用于#12-34.234-3.234。你好世界

    .*?只会匹配到4,然后找到点并且会匹配,懒惰导致它停止搜索更多令牌以供消费

答案 1 :(得分:3)

您可以使用:

/#([^.]*)\./

使用[^.]*匹配除了点(不需要在括号内转义点)之后的任何内容的序列,后跟一个点。您想要的结果是在第一组中。例如在javascript中:

/(?:#)([^.]*)(?=\.)/.exec("#Q-111-111-1111.")[1]

返回

Q-111-111-1111

如果您不想使用组,可以应用以下正则表达式(不幸的是,因为它不支持正面的lookbehinds,不适用于javascript):

/(?<=#)[^.]*(?=\.)/

答案 2 :(得分:2)

限制性的东西会避免误报结果:

(#[A-Z](-\d+){3})

这个将匹配#的字符串构建,后跟1个大写字母和3个以-开头的数字组。

您可以对其进行测试here

我更喜欢不使用最终的.因为你可能想解析那些字符串:

  

您的订单#Q-111-111-1111已发送。

     

按照您的订单#Q-111-111-1111,我们永远不会给您回电,您再也看不到您的钱了。

您可以更加严格,只匹配具有大量数字的字符串:

#([A-Z])-(\d{3})-(\d{3})-(\d{4})

一件好事是,每个相关部分现在都在不同的组中。

您可以对其进行测试here