2015-02-09 36 views
-1

從這個例子的右邊或左邊:的Python re.split和附加匹配組到分離

>>> re.split('(\W)', 'foo/bar spam\neggs') 
['foo', '/', 'bar', ' ', 'spam', '\n', 'eggs'] 

是存在於捕獲組與右側或左側部分聯繫起來的簡單方法分裂?例如。使用相同的正則表達式/捕獲組,但產生:

['foo', '/bar', ' spam', '\neggs'] 

或可選

['foo/', 'bar ', 'spam\n', 'eggs'] 

我敢肯定,你可以通過改變實際的正則表達式實現它,但是這不是重點(和我們可以修改該示例以使匹配更加複雜,因此無法僅僅重新使用它們並將它們推向右側或左側是一種真正的痛苦)。

不幸的是,它看起來像使它成爲一個非捕獲組只下降從匹配相應的字符:

>>> re.split('(?:\W)', 'foo/bar spam\neggs') 
['foo', 'bar', 'spam', 'eggs'] 

舉另一個例子,考慮如果你有從行爲不端的CSV文件中的一些文本。每行只有一個實際的逗號分開,但不小心某些行在其中一個字段中也有逗號。幸運的是,不分裂的逗號總是跟着一個空格。

csv_data = [ 
    'Some good data,Id 5', 
    'Some bad data, like, really bad, dude,Id 6' 
] 

在這種情況下,我們的目標是處理這個:通過使用簡單的re.split

[['Some good data', 'Id 5'], 
['Some bad data, like, really bad, dude', 'Id 6']] 

使用map(lambda x: re.split(",(?:\S)", x), csv_data)產生

[['Some good data', 'd 5'], 
['Some bad data, like, really bad, dude', 'd 6']] 

,並使用map(lambda x: re.split(",(\S)", x), csv_data)產生

[['Some good data', 'I', 'd 5'], 
['Some bad data, like, really bad, dude', 'I', 'd 6']] 

那麼,什麼是一個通用的方法來re.split,將工作同樣爲這兩種情況?基本上這是我可以在一個功能包,像

def my_split(regex_chars, my_strs): 
    return map(lambda x: re.split(...regex_chars..., x), my_strs) 

使得兩個

my_split(r'(\W)', ['foo/bar spam\neggs']) 

my_split(r',(\S)', csv_data) 

每個返回預期輸出從上方。

:看來這是不可能在短短re,但也有可能與基礎上,拆分是否是零寬度與否regexre一些混合物。

+0

如果你堅持使用're.split()' – hwnd 2015-02-09 02:43:00

+0

,你將需要修改正則表達式,它不會直接通過re.split在分割不能在邊界上工作。 – 2015-02-09 02:43:13

+0

@hwnd那麼上面的評論就是答案。 – 2015-02-09 02:47:40

回答

3

不,這是不可能的。我不知道有任何正則表達式引擎支持這種事情。拆分意味着拆分:您可以保留拆分器或丟棄拆分器,但不能將拆分器與拆分器之間的碎片結合,因爲拆分器與其分離的內容截然不同。

隨着regex模塊,你可以做到這一點很簡單,但它確實需要改變原來的正則表達式:

>>> regex.split('(?=\W)', 'foo/bar spam\neggs', flags=regex.V1) 
['foo', '/bar', ' spam', '\neggs'] 

不同於內置re模塊,該regex模塊允許分裂零寬度匹配,所以你可以使用前視來分割下一個字符匹配的位置\W

在你在編輯添加的例子,你可以用甚至用普通re超前做,因爲分離器不是零寬度:

>>> map(lambda x: re.split(",(?=\S)", x), csv_data) 
[['Some good data', 'Id 5'], 
['Some bad data, like, really bad, dude', 'Id 6']] 
+0

你能解釋一下'regex.V1'標誌嗎? – 2015-02-09 02:56:39

+0

@AvinashRaj:它在我鏈接到的文檔頁面上進行了描述。 – BrenBarn 2015-02-09 02:57:47

+0

我會對它進行一些不同的表徵(參見我的擴展示例,並在問題的底部添加了逗號)。它不一定是零寬度分割。在逗號示例中,您希望通過單個字符(逗號)進行拆分,但只能使用具有特定屬性的特定逗號(它們緊跟在非空格字符後面)。無論那個非空間性格是什麼都不重要,也不是分裂的一部分(只是承認逗號的一部分),而且非空間性格需要放在某處(在我的情況下是分裂的權利)。也許*這個*可以實現? – ely 2015-02-09 02:58:39

2

是這樣的情況下,你可以使用基於負前瞻像下面的正則表達式。

>>> csv_data = [ 
    'Some good data,Id 5', 
    'Some bad data, like, really bad, dude,Id 6' 
] 
>>> [re.split(r',(?!\s)', i) for i in csv_data] 
[['Some good data', 'Id 5'], ['Some bad data, like, really bad, dude', 'Id 6']] 

,(?!\s)匹配所有不會跟着空格字符的逗號。根據匹配的逗號分割將會給你想要的輸出。

+0

我想這適用於我的情況,但是你也可以很容易地爲快速修飾符添加到正則表達式中的情況(例如在這種情況下易於使用'!')來輕鬆地構建圖像。它仍然沒有考慮到僅僅使用捕獲組來識別剩餘的正則表達式所具有的屬性,但是然後*不*匹配或丟棄捕獲組本身。 – ely 2015-02-09 03:02:32

+0

@ Mr.F:「識別正則表達式的其餘部分具有的屬性,但不匹配該部分」是查找的目的。如果你想分割的是「* next *字符是X」,那麼你不想在X上分割,你應該設計分割正則表達式來直接編碼你想要分割的位置,下一個字符是X. – BrenBarn 2015-02-09 03:06:11

+0

'!'不是修飾符。 '(?!..)'被稱爲負面看法。 – 2015-02-09 03:08:04