2017-04-19 74 views
1

我有一個字符串,它看起來是這樣的:用匹配組中的下劃線替換空格字符?

"(case when Campaign='Back to School' and VariableName='Total_FB_Spend' then VariableValue else 0 end) AS Back to School_Total_FB_Spend,(case when Campaign='Back to School' and VariableName='Total_FB_Imp' then VariableValue else 0 end) AS Back to School_Total_FB_Imp"

我想使用Python正則表達式後刪除在列名中的空格「端)AS」字符。結果應該成爲這樣的事情

"(case when Campaign='Back to School' and VariableName='Total_FB_Spend' then VariableValue else 0 end) AS Back_to_School_Total_FB_Spend,(case when Campaign='Back to School' and VariableName='Total_FB_Imp' then VariableValue else 0 end) AS Back_to_School_Total_FB_Imp"

我能夠匹配那些我有興趣在Python [example here]使用正則表達式的部分,但我想知道如何優雅地(例如,一個襯墊或在Python化方式)替換匹配的組中的空格字符。

+1

請在下面檢查我的答案。請注意,雖然基於lookbehind的正則表達式在這種情況下更爲優化,但我決定儘可能少地改變原始模式本身,以顯示如何在單個lambda替換中處理多個*組。 –

回答

1

你需要一個re.sub用lambda表達式作爲替換參數:

import re 
s = "(case when Campaign='Back to School' and VariableName='Total_FB_Spend' then VariableValue else 0 end) AS Back to School_Total_FB_Spend,(case when Campaign='Back to School' and VariableName='Total_FB_Imp' then VariableValue else 0 end) AS Back to School_Total_FB_Imp" 
pat = r'(end\) as)([^,]*)' 
print(re.sub(pat, lambda m: "{}{}".format(m.group(1), m.group(2).replace(" ", "_")), s)) 

Python demo

請注意,我用更高效的([^,]*)更換你的(.*?(,|$)),比任何零個或多個字符等,。現在,整個正則表達式匹配:

  • (end\) as) - 第1組:end) as
  • ([^,]*) - 組2:比,

然後其他任何零個或多個字符,與lambda m: "{}{}".format(m.group(1), m.group(2).replace(" ", "_")),的內容第一個捕獲組被複制回結果不變,第二個組的內容被修改爲.replace(" ", "_")。當然,如果可能有任何空格,你可以運行另一個正則表達式,re.sub(r'\s+', '_', m.group(2))

+0

Stribizew非常感謝你對你的建議解決方案如何在一起工作的詳細解釋!它像一個魅力。我最終使用're.sub(r'\ W +','_',m.group(2))',因爲它更容易。我對'lambda'還不是很熟悉,所以我想知道它是如何返回匹配正則表達式模式的組(沒有我們在'lambda'語句中寫入任何明確的're.search(pat,s)')。如果你不介意進一步解釋或者指導我一個好的資源,這就解釋了我非常感謝! :) – user1330974

+0

非常感謝您的詳細解釋!由於患者/詳細說明,您的答案非常有幫助和清晰。今天我瞭解到're.sub'將匹配的對象傳遞給'lambda'(或'lambda'捕獲're.sub'中的任何匹配項)。很強大! – user1330974

+1

對不起,格式化。重新發布評論:實際上,lambda中的「m」代表一個匹配數據對象。當你使用're.sub'時,正則表達式引擎搜索模式的所有非重疊事件,並且當找到匹配時,所有的捕獲組形成'.group()'。因此,'(a)|(b)'包含2個捕獲組,並且當在'abc'字符串上使用時,首先找到'a'(在'm.group(1)'中使用'a',在m.group(2)')中爲空(取決於Python版本)。您可以訪問任何捕獲組或整個匹配('m.group()'),並根據您的需要進行操作(轉換爲int,增量等) –

1

受@Wiktor啓發的另一種解決方案。

import re 
s = "(case when Campaign='Back to School' and VariableName='Total_FB_Spend' then VariableValue else 0 end) AS Back to School_Total_FB_Spend,(case when Campaign='Back to School' and VariableName='Total_FB_Imp' then VariableValue else 0 end) AS Back to School_Total_FB_Imp" 
pat = r'(?<=end\) as)[\w\s]*(?=,)' 
print(re.sub(pat, lambda m: m.group(0).replace(" ", "_"), s, flags=re.IGNORECASE)) 

這裏我們使用先行和正則表達式的回顧後功能只匹配,我們要改變的字符串。正則表達式將匹配單詞字符[a-zA-Z0-9_]空格之前的任何序列end) as,然後是,。主要區別在於比賽只包含一個組。

+1

請注意,後視作爲捕獲組不像一個lookbehind模式應該是固定的長度。你不能在那裏使用'\ s *'和'\ w +'。 –

+1

確實,但是因爲我們正在尋找一個固定的後綴和後綴,所以在這種情況下這不會成爲問題。 – Jonas

+0

@Jonas謝謝你的替代建議。我在這裏第一次在正則表達式中學到了一些有關前瞻/後視模式的知識。當我嘗試上面分享的代碼時,我收到了'IndexError:no such group'。 – user1330974

相關問題