2014-05-05 77 views
2

我有這樣的代碼,以查找文本:):(空間正則表達式中

for match in re.finditer(r':\)|:\(', ":) :):(:) :("): 
    print match.span() 

,給我這樣的回答:

(0, 2) 
(3, 5) 
(5, 7) 
(8, 10) 
(12, 14) 

它的工作原理,但我需要它給我只有那些單詞是單獨的(旁邊沒有其他字符)所以答案是:

(0, 2) 
(8, 10) 
(12, 14) 

我嘗試添加\b但沒有得到答案

這是添加(x)與模式

for match in re.finditer(r'(?<![\w()]):(?:\)|\()(?![\w:])', ":) :):(:) :( (x)"): 
    print match.span() 

顯示了一種情形:

(0, 2) 
(8, 10) 
(12, 14) 

ANS我想

(0, 2) 
(8, 10) 
(12, 14) 
(16, 19) 

回答

3

如果沒有其他字符,你的意思是沒有其他可見的字符,使周圍的笑臉唯一允許的字符空間(包括標籤),你可以使用這樣的事情:

for match in re.finditer(r"(?:(?<=\s)|(?<=^)):[()](?=\s|$)", ":) :):(:) :("): 
    print match.span() 

(?:(?<=\s)|(?<=^))確保有任一個空白字符或笑臉前的行的開頭,

:[()]匹配:接着爲無論()

(?=\s|$)確保在笑臉後有空白字符或行尾。

如果你還想要匹配笑臉x),你可以這樣做:如果你想匹配x(以及

r"(?:(?<=\s)|(?<=^))(?::[()]|x\))(?=\s|$)" 

,它變得更容易一些:

r"(?:(?<=\s)|(?<=^))[x:][()](?=\s|$)" 

[ ... ]是一個角色類,你不需要逃避那裏的東西。請謹慎對待-^的展示位置,因爲這兩者在角色等級中具有特殊含義。

編輯:看來我錯了額外的笑臉X)就(意爲:):((x)),這將是東西有點像:

r"(?:(?<=\s)|(?<=^))(?::[()]|\(x\))(?=\s|$)" 

重新編輯:實際上,積極主張可以縮短負數,這使得它更簡單:

r"(?<!\S)(?::[()]|\(x\))(?!\S)" 
+0

我得到了' v#無效表達式請仔細閱讀我的問題,我編輯了一下,解釋得更好一些。 – Andres

+0

@Andres糟糕,我幾乎總是忘記了Python不支持可變寬度lookbehind ...我修復了這個部分,我確實考慮過編輯。 – Jerry

3

:,()都是非字字符,所以\b不起作用。你會使用逆,\B

r'\B:(?\)|\()\B' 

凡邊界上\w\W或反之亦然之間\b比賽,\B只有兩個\w或兩個\W點之間的匹配。由於:和括號字符都是\W字符,這意味着它們必須位於另一個非單詞字符(或行的開始或結尾)旁邊。

但是這仍然會匹配其他笑臉。

完全排除你需要同時使用負前瞻和負查找落後於其他表情:

r'(?<![\w()]):(?\)|\()(?![\w:])' 

這是說:

  • (?<![\w()]):無字的字符或括號前笑臉(字符串的開頭很好)
  • (?![\w:]):笑臉後沒有單詞字符或冒號(字符串結尾很好)

演示:

>>> for match in re.finditer(r'(?<![\w()]):(?:\)|\()(?![\w:])', ":) :):(:) :("): 
...  print match.span() 
... 
(0, 2) 
(8, 10) 
(12, 14) 

爲您更新病毒碼版本,你顯然不介意(在前面,所以我們從模式之前的排除的字符刪除,並更新:[x:]匹配任一種x或冒號:

r'(?<![\w)])[x:](?:\)|\()(?![\w:])' 

演示:

>>> for match in re.finditer(r'(?<![\w)])[x:](?:\)|\()(?![\w:])', ":) :):(:) :((x)"): 
...  print match.span() 
... 
(0, 2) 
(8, 10) 
(12, 14) 
(16, 18) 
+0

如果我需要添加另一種模式?即**「(x)|:\)|:\(」**而不是**「:\)|:\(」**。是否需要實現另一種方法? – Andres

+0

@Andres:只要你可以表達什麼應該*不*在笑臉之前,它會工作,在這種情況下,'x'已經是'[\ w()]'的一部分,所以應該工作得很好 –