36

I need to add a number to a backreference while doing a replace operation.

e.g. I am rewriting a URL

www.site.com/doc.asp?doc=321&language=1

to

www.site.com/headline/100321.article

I'm doing a simple replace, but I need to add 100,000 to the doc ID. What I have below works so far without adding anything.

s/.*doc=(\d+).*/www.site.com\/headline\/$1.article/g;

How can I add 100,000 to $1?

Note, you can't just add 100 before the number because the doc ID might be > 999.

Worthwelle
  • 1,244
  • 1
  • 16
  • 19
Kevin
  • 1,200
  • 1
  • 11
  • 19
  • 2
    I managed to do a simple math expression by using the 'e' flag. s/.*doc=(\d+).*/$1+100000/e but that way it only returns the number and not the 'wrapping' URL. I need to concatenate this with the rest of the string. – Kevin Mar 09 '11 at 11:26
  • +1 Thanks for this question. Helped me do something similar with the Linux program `rename`. – Geoff Nov 29 '11 at 16:05

3 Answers3

38

using Perl:

s/.*doc=(\d+).*/"www.site.com\/headline\/".($1+100000).".article"/e;

as you've done with e flag, the right part becomes now an expression. so you have to wrap the non-capture part as strings.

Bart Kiers
  • 166,582
  • 36
  • 299
  • 288
Metaphox
  • 2,085
  • 2
  • 21
  • 34
  • Do you happen to know if this works in the .Net regex parser? – Kevin Mar 09 '11 at 12:10
  • 2
    @Kevin, no it does not. The `($1+100000)` part is being evaluated by Perl, regex has nothing to do with this. But, it looks like you're already using Perl, no? – Bart Kiers Mar 09 '11 at 12:11
  • I was using Perl to get the regex correct before "implanting" it into a c# program! I think I'm going to end up doing it programmatically in the end, but I'm pretty sure this answer will help a lot of folks with a similar problem. – Kevin Mar 09 '11 at 12:17
7

That's not possible in regex. Regex only matches patterns, it doesn't do arithmetic.

The best you can do is something verbose like:

match       replace

(\d{6,})    $1
(\d{5})     1$1
(\d{4})     10$1
(\d{3})     100$1
(\d{2})     1000$1
(\d)        10000$1
Bart Kiers
  • 166,582
  • 36
  • 299
  • 288
  • Would it be possible to create a regex that does do arithmetic though? Like an extremely complicated one? I know it would be far from the most efficient way to do it, but it would still have value as a technical exercise. That's actually how I found this page (through a related Google search): because I was curious if this was possible or if anyone had done it. – flarn2006 Aug 29 '16 at 21:00
  • @flarn2006, no, like I said, regex only matches patterns, it doesn't do arithmetic. Regex will only tell you "yes, the text matches the pattern you provided (or no, it didn't)", nothing else. – Bart Kiers Aug 30 '16 at 21:05
  • What about making a regex that matches an arithmetic statement that's correct? Like "45+6=51" would match, but "38+16=4" would not. Would that be possible in theory? – flarn2006 Aug 31 '16 at 15:13
  • @flarn2006 It's possible, but only via a more complex flavor of regex, or with a loop, and even then using a loop means you have to convert to unary meaning adding 100000 would mean you'd need to store a 100kb string – somebody Aug 08 '17 at 12:47
3

If you only have a few articles you could just brute force it

...doc=322 -> www.site.com/headline/100322.article
...doc=323 -> www.site.com/headline/100323.article
...doc=324 -> www.site.com/headline/100324.article
...etc

Math in regex, you see it here first.