RegEx优先考虑最长的模式

时间:2016-03-04 00:31:26

标签: regex r

我有一些字符串来搜索与正则表达式的匹配。

foo
AB0001
AB0002 foo
foo AB0003
foo AB0004A AB0004.1
AB0005.1 foo AB0005A bar AB0005

所需的匹配是每行一个ID,而末尾带有字母的ID应该优先,而带有.1的ID应该被忽略。

foo                              -> no match
AB0001                           -> AB0001
AB0002 foo                       -> AB0002
foo AB0003.1                     -> no match
foo AB0004A AB0004.1             -> AB0004A
AB0005.1 foo AB0005A bar AB0005  -> AB0005A

我认为我可以轻松地使用交替|符号给出的优先级来在最后用大写字母对ID进行优先级排序,但是总是会给出多个匹配项。

我的建议: regex101.com/r/yP5kX4/1

Offtopic:何时使用以^开头的整个RegEx以$结尾并使用捕获/非捕获组,何时应尽可能缩短RegEx?

4 个答案:

答案 0 :(得分:1)

这是一种方式。它有点复杂,因为你需要懒得找到 ID的第一个实例。

此正则表达式将用于多行模式。在开头添加(?m) 正如你所知的正则表达式

结果ID位于捕获组1中。

^.*?\b([A-Z]+\d+[A-Z]|[A-Z]+\d+(?!\.\d)(?!.*?\b[A-Z]+\d+[A-Z]))\b

解释

 ^                                  # Beginning of string
 .*?                                # Any char, lazy to get first instance
 \b    
 (                                  # (1 start), the ID
      [A-Z]+ \d+ [A-Z]                   # Priority, with trailing letter
   |                                   # or,
      [A-Z]+ \d+                         # no trailing letter
      (?! \. \d )                        # no dot digit after digit
      (?! .*? \b [A-Z]+ \d+ [A-Z] )      # and only if not a trailing  letter id downstream
 )                                  # (1 end)
 \b     

答案 1 :(得分:0)

我想以这种方式检测 R 3.1.3 中的字符串:

grepl("(?<!\\.)[A-Z0-9]+?(?=\\s)", subject, perl=TRUE);

根据您在问题中发布的输入,输出将为:

  

<强> INPUT

foo
AB0001
AB0002 foo
foo AB0003
foo AB0004A AB0004.1
AB0005.1 foo AB0005A bar AB0005

-

  

<强>输出

  • AB0001
  • AB0002
  • AB0003
  • AB0004A
  • AB0005A

答案 2 :(得分:0)

以下正则表达式应该:

(AB(?:[0-9A-Z]{5}|[0-9]{4}))(?:\s+)

我在ID匹配后添加了一个非捕获组(?:\ s +)来捕获空间。 演示是HERE:

我的想法:(如果我错了,请纠正我)

何时使用以$结尾的整个RegEx? 如果正则表达式匹配整个字符串的开始(^)到结束($)。

使用捕获/非捕获组? 如果要提取/引用该信息,请使用捕获组; 如果您只想匹配,则使用非捕获组,但不提取和引用。请查看:What is a non-capturing group? What does a question mark followed by a colon (?:) mean?

我应该何时尽可能缩短RegEx? 越短越好,只要它起作用

答案 3 :(得分:0)

\b(AB\d{4}(?!\.\d)[A-Z]?)\b

DEMO

那是AB后跟四位数字,后面不能跟一个十进制数字序列,但可能以一个字母结尾。单词边界(\b)有助于确保匹配的序列不是像那样外观的更长序列的一部分。

基于交替的解决方案永远不会起作用。确实,如果交替的两个或多个分支可以在给定点匹配 ,则始终选择第一个分支(无论如何,大多数正则表达式都是如此)。但这对你没有帮助,因为正则表达式引擎始终支持第一个(最左边)匹配;这是它的最高优先级。所以第一场比赛无论胜利的哪个分支都会胜出。

对于锚点(^$),它们通常只在你想要匹配整个字符串时才需要,或者在多线模式下匹配整行(和BTW,因为你'不使用它们,你不需要/m标志;它所做的就是改变锚点的含义。)

捕捉群组的问题在这里很有趣,因为你不需要它们。我使用它的唯一原因是因为Regex101网站没有在侧面板中显示匹配,除非它们在捕获组中。在一个非常有用的网站上,这是一个恼人的小故障。但一般来说,当您需要提取匹配的特定部分时,或者需要在正则表达式中使用反向引用时,可以使用捕获组。