2016-03-04 67 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網站沒有顯示側面板中的匹配,除非它們在捕獲組。這是一個非常有用的網站令人討厭的故障。但是一般來說,當您需要提取匹配的特定部分時,或者需要在正則表達式本身中使用反向引用時,您可以使用捕獲組。