2012-12-01 53 views
1

我一直很難理解正則表達式。在網絡搜索的幫助下,我總是設法通過某種方式。猜猜我從來沒有打擾過,然後真正學習。抱歉。Python正則表達式替換

但我需要再次幫助他們。

我有一個像

d = {'account_id':a_value,'group_id':g_value,'other_id':o_value } 

的字典,我有一堆像字符串:

s1 = r'^settings/usergroups/(?P<group_id>\d+)/cargroups/$' 
s2 = r'^settings/usergroups/(?P<group_id>\d+)/other/(?P<other_id>\d+)/$', 
s3 = r'^settings/account/(?P<account_id>\d+)/other/(?P<other_id>\d+)/$', 

如何Ø從字典匹配值替換字符串中的(?P<group_id>\d+)(?P<account_id>\d+)(?P<other_id>\d+)

+0

看起來它可能與Django相關。如果是這樣,你有沒有考慮過https://docs.djangoproject.com/en/dev/topics/http/urls/#reverse-resolution-of-urls? – Thomas

+1

是的,我從我的django項目中選取了一個url。這個問題本身並不像django那樣相關,儘管django網站通過驗證字符串'settings/usergroups/12/cargroups /是否匹配給定模式之一來自己處理所有這些事情。我不需要匹配模式的網址。我需要從模式和值創建字符串。所以即使我的例子是從Django中獲取的,但這個問題本身是更爲通用的python,並不涉及django。 –

+0

這個問題與正則表達式沒有多大關係。 –

回答

2

正則表達式可以包含嵌套的括號內。

但是,Python regular expressions can not match strings containing arbitrarily deep nested parentheses尊重嵌套結構。 (可以使用Perl的遞歸正則表達式。)

所以,如果你的使用情況涉及到的字符串不包含嵌套paretheses, 那麼以下就足夠了,但要注意仔細不需要額外的括號下面最後結果:

import re 
d = {'account_id':'a_value','group_id':'g_value','other_id':'o_value' } 

tests = (r'^settings/usergroups/(?P<group_id>\d+)/cargroups/$', 
     r'^settings/usergroups/(?P<group_id>\d+)/other/(?P<other_id>\d+)/$', 
     r'^settings/account/(?P<account_id>\d+)/other/(?P<other_id>\d+)/$', 
     r'^settings/usergroups/(?P<group_id>(\d+|\w))/other/(?P<other_id>\d+)/$' 
     ) 
metapat = r'\(\?P<(.*?)>.*?\)' 
for t in tests: 
     result = re.sub(metapat, r'{\1}', t) 
     if result: 
      print(result.format(**d)) 

產生

^settings/usergroups/g_value/cargroups/$ 
^settings/usergroups/g_value/other/o_value/$ 
^settings/account/a_value/other/o_value/$ 
^settings/usergroups/g_value)/other/o_value/$ 

如果您確實需要解析嵌套圓括號,那麼您將需要與re不同的解析器。例如,Pyparsing可以處理嵌套表達式。

+0

嗯,對。感謝你的回答 :)。最終你的解決方案與dedoco的答案差不多。它雖然有點fancier方式雖然:)。我仍然試圖瞭解django如何做同樣的事情 - 它可以採取模式,驗證值是否匹配模式,然後生成包含該值的url(基本上是字符串)。 –

+0

認爲你已經理解了我所努力達到的最好結果,並以最佳方式解釋了我可以或不能用正則表達式做什麼。這就是爲什麼虐待這個人​​。 –

0

此問題與正則表達式無關;但更多的是爲特定視圖生成網址。

首先,讓您的生活輕鬆,name your url patterns

urlpatterns = patterns('', 
    (r'^settings/usergroups/(?P<group_id>\d+)/cargroups/$', 'car_groups_by_id'), 
    # and so on 
) 

然後在你的views.py,如果你想將用戶重定向:如果要生成的URL

from django.shortcuts import redirect 

def foo(request): 
    return redirect('car_groups_by_id',group_id=1234) 

您模板:

{% url 'car_groups_by_id' group_id=1234 %} 

如果您只是想打印網址:

>>> from django.core.urlresolvers import reverse 
>>> reverse('car_groups_by_id',kwargs={'group_id': 1234}) 

這樣做的一般,非Django的方法是使用內置的template strings

>>> from string import Template 
>>> t = Template('foo/bar/$group_id/zoo/') 
>>> t.substitute(group_id=1234) 
'foo/bar/1234/zoo/' 

在這兩種情況下,因爲你是這不是一個正則表達式的問題不要試圖匹配某些東西 - 只需替換字符串中的標記即可。恰好碰巧你的示例字符串的標記是python正則表達式。

+0

這絕對不是我所問的。謝謝你嘗試。就像我在評論中所說的那樣。這不是django相關的。我正在尋找方式來取代(?P \ d +)字符串中的數字。但感謝您指出django網址模板標籤在內部做到了這一點。我看着它。 –

+0

你在評論中說:「我不需要匹配模式的url,我需要從模式和值創建字符串」,並且因爲你使用了django url - 所以我提到了這一點。不過,我已經用非Django的方式更新了答案。 –

+0

太棒了!謝謝。字符串&模板示例之後的註釋是點亮的。令牌確實是python正則表達式,我確定有一種方法可以將整個表達式部分替換爲值。畢竟你可以創建正則表達式來創建/驗證正則表達式,對吧?仍然。現在看來,在這種情況下,內部是什麼djangos反向是我需要的東西:) –

1

如果你想要去簡單的字符串修改,只是取代在d有關其價值的字符串,你可以這樣做:

for key in d: 
    s = s.replace(key,str(d[key])) 
s = s.replace('(?P<','').replace('>\d+)','') 
+0

是的,這將是一種做法。儘管如此,這種情況仍然存在。每個值的模式可能不同。當然,在這種情況下他們是一樣的,但他們可能會有所不同。並且用於替換模式的值也可以/應該與模式匹配。 –

+0

模式中是否存在一些規律? – jojo