1

I have always had hard time understanding regular expressions. With the help of web searches i have always managed to pull through somehow. Guess i have never bothered to really learn then. Sorry.

But i need help with them yet again.

I have a dict like

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

And i have bunch of strings like:

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+)/$',

How can O replace the (?P< group_id >\d+), (?P< account_id >\d+), (?P< other_id >\d+) in the strings with matching values from dict?

Chris Seymour
  • 83,387
  • 30
  • 160
  • 202
Odif Yltsaeb
  • 5,575
  • 12
  • 49
  • 80
  • Looks like it might be Django-related. If so, have you considered https://docs.djangoproject.com/en/dev/topics/http/urls/#reverse-resolution-of-urls? – Thomas Dec 01 '12 at 09:40
  • 1
    Yes i took the urls from one of my django project. The question itself is not so much django related though as django urls takes care of all this by itself by validating if string 'settings/usergroups/12/cargroups/ matches one of the given patterns. I dont need to match the urls for pattern. I need to create string from pattern and values. So even though my examples were taken from django, the question itself is more generic python related not django related. – Odif Yltsaeb Dec 01 '12 at 09:46
  • This question is not much related to regexp either. – Roman Bodnarchuk Dec 01 '12 at 09:50
  • I assumed my problem could be solved with regexp - thats the reason i tagged the question as regexp. I assumed it because i once saw some example where python datetime was constructed from dict using regexp. I might remember wrong though. In any case replacing something like 'account_id' in string with number is pretty simple. but can (?P – Odif Yltsaeb Dec 01 '12 at 09:58

3 Answers3

2

Regular expressions can contain nested parentheses.

However, Python regular expressions can not match strings containing arbitrarily deep nested parentheses in a way that respects the nested structure. (It is possible using Perl's recursive regular expressions.)

So, if your use case involves strings that DO NOT contain nested paretheses, then the following suffices, but note carefully the undesired extra parenthesis in the last result below:

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))

yields

^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/$

If you do need to parse nested parentheses, then you'll need a different parser than re. Pyparsing, for example, can handle nested expressions.

Community
  • 1
  • 1
unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
  • Hmmm right. Thanks for the answer :). In the end what your solution does is more or less the same that dedoco's answer does. It does it in bit fancier way though :). Im still trying to understand how django does this same thing - it can take the pattern, validate if value matches the pattern and then generate url (string basically) from it which contains the value. – Odif Yltsaeb Dec 01 '12 at 10:52
  • Think you understood the best what i tried to achieve and explained in a best way what i can or cant do with regex. Thats why ill accept this one. – Odif Yltsaeb Dec 05 '12 at 08:03
1

If you want to go with simple string modifications and just replace the strings by their value associated in d, you can do this:

for key in d:
    s = s.replace(key,str(d[key]))
s = s.replace('(?P<','').replace('>\d+)','')
j-i-l
  • 10,281
  • 3
  • 53
  • 70
  • Yes this would be one way of doing it. This sort of goes around the point though. The pattern can be different for each value. Sure they are the same in this case, but they could be different. And value that is used to replace the pattern could/should match the pattern too. – Odif Yltsaeb Dec 01 '12 at 10:36
  • Are there then some regularities in the patterns? – j-i-l Dec 01 '12 at 10:40
0

This problem is not related to regular expressions; but more of generating URLs for a particular view.

First, to make your life easy and name your url patterns:

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

Then in your views.py, if you want to redirect a user:

from django.shortcuts import redirect

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

If you want to generate the url in your templates:

{% url 'car_groups_by_id' group_id=1234 %}

If you just want to print the URL:

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

The generic, non-django way of doing this would be to use the built in template strings:

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

In either case, this is not a regular expression problem since you are not trying to match something - simply replace tokens in strings. It just so happens that your example string's tokens are python regular expressions.

Burhan Khalid
  • 169,990
  • 18
  • 245
  • 284
  • This is absolutely NOT what i asked. thanks for trying though. Like i said in my comment. this is NOT django related. Im looking for way to replace (?P\d+) in string with number. But thanks for pointing out that django url templatetag does just that internally. Ill look into it. – Odif Yltsaeb Dec 01 '12 at 10:16
  • You said in your comment "I dont need to match the urls for pattern. I need to create string from pattern and values.", and since you used django urls - that's why I mentioned that. However, I have updated the answer with the non-django way to do it. – Burhan Khalid Dec 01 '12 at 10:22
  • Awesome! Thanks. The comment after string & Template example is spot-on. The tokens are indeed python regular expressions and im sure there is a way to replace whole this expression part with the value. After all you CAN create regular expression to create/validate regular expression, right? Still. for now it seems that what djangos reverse does internally is the stuff i need in this case :) – Odif Yltsaeb Dec 01 '12 at 10:28