2016-03-04 45 views
0

我得到了一些字符串来搜索正则表达式的匹配。正则表达式优先考虑最长的模式

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

的期望的匹配是每行一个ID而与在端部具有字母ID应该被优先,而具有0.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:当使用正则表达式整体开始^结束与$与捕获/非捕获组工作时,我应该写的正则表达式尽可能短?

+0

您无法通过R中的纯正PCRE/TRE正则表达式实现此功能。 –

回答

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  
+0

感谢您的操作!负面的预测只是放弃了“匹配”被识别?我理解'|'和第二个之后的第一个表达式,但是我没有得到第三个表达式。为什么这需要?也许仅仅如果字符串出现像“AB0001A AB0001.1 AB0002A”一样?所以第一个ID被标记为匹配,然后负向前瞻发现第三个ID,并通过将'AB0002A'作为最终匹配而丢弃先前的匹配? – heiiRa

+0

@heiiRa - 几乎正确。这是基本表达式[[A-Z] + \ d + [A-Z]?'它只是被分割为_OR_(交替))。引擎测试每个字符位置的交替。如果找不到'[A-Z] + \ d + [A-Z]',它会匹配[A-Z] + \ d +',如果可以的话。第一个_assertion_'(?!\。\ d)'使它停止匹配_any_'AB0001.1',第二个断言'(?!。*?\ b [AZ] + \ d + [AZ])'将其停止匹配当前候选人'AB0001'_如果右边有任何'AB0001B'。然后它检查每个字符,直到它到达匹配的“AB0001B”。 – sln

0

我想检测ř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
0

下面的正则表达式应该做的:

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

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

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

当使用正则表达式整体开始与$ ^结束? 如果正则表达式匹配从整个字符串的开始(^)到结尾($)。

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

我应该在什么时候写RegEx尽可能短? 时间越短越好,只要它的作品

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

DEMO

这是AB其次是四位数字,一定不能跟一个十进制数序列,但可能以字母结尾。字边界(\b)有助于确保匹配的序列不是像发生在一样的较长序列的一部分。

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

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

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