tags:

views:

1231

answers:

10

I need to replace some 2- and 3-digit numbers with the same number plus 10000. So

Photo.123.aspx

needs to become

Photo.10123.aspx

and also

Photo.12.aspx

needs to become

Photo.10012.aspx

I know that in .NET I can delegate the replacement to a function and just add 10000 to the number, but I'd rather stick to garden-variety RegEx if I can. Any ideas?

+6  A: 

I think that using a RegEx for the match, and a function for the replace is most appropriate in this case, you are doing simple math, use something that is designed to do it.....

Mitchel Sellers
I would have to agree to some extent, although depending on the circumstances Regex'ing it is not a bad solution...
SoloBold
A: 

did you try just using PadLeft?

StingyJack
As I said, I'm trying to do this in RegEx. If I'm going to write a function to do it, I'll just do simple arithmetic rather than string manipulation.
Herb Caudill
+1  A: 

If it's only two or three digit numbers:

(I assume you are using .NET Regex since we are talking about .aspx files)

Check for: Photo\.{\d\d\d}\.aspx

Replace with: Photo.10\1.aspx

Then check against: Photo\.{\d\d}\.aspx

Replace with: Photo.100\1.aspx

SoloBold
A: 

This appears to do what you want:

static public string Evaluator(Match match) 
{
     return "Photo.1" 
            + match.Groups[1].Captures[0].Value.PadLeft(4, '0')
            + ".aspx";
}

public void Code(params string[] args)
{
     string pattern = @"Photo\.([\d]+)\.aspx";
     string test = "Photo.123.aspx";
     Regex regex = new Regex(pattern);
     string converted = regex.Replace(test, Evaluator) 
     Console.WriteLine(converted);
}
James Curran
If I'm going to wire up an evaluator I might as well just use simple arithmetic rather than string manipulation. I was hoping for some regex-only wizardry.
Herb Caudill
there is no regex wizardry to do math, it is only for string manipulation
Nick Berardi
+5  A: 

Is there any reason it has to be VB.NET?

Perl

s(
  Photo\. (\d{2,3}) \.aspx
){
  "Photo." . ($1 + 10000) . ".aspx"
}xe
Brad Gilbert
Yeah - very cool that you can do that in Perl though.
Herb Caudill
TIMTOWTDI ( There Is More Than One Way To Do It )
Brad Gilbert
+1  A: 

James Curran did it little faster than me but well here is what I have for you. Think it's the smallest code you can have with Regex to do what you want.

        Regex          regex = new Regex(@"(\d\d\d?)", RegexOptions.None);
        string result = regex.Replace(@"Photo.123.asp", delegate(Match m) 
                                                {
                                                    return "Photo.1"
                                                        + m.Groups[1].Captures[0].Value.PadLeft(4, '0')
                                                        + ".aspx";
                                                }
        );
Daok
+2  A: 

Try the following:

"Photo\./d\.aspx" and replace with "Photo.1000$1.aspx"
"Photo\./d/d\.aspx" and replace with "Photo.100$1.aspx"
"Photo\./d/d/d\.aspx" and replace with "Photo.10$1.aspx"

That is the only way I see this happening.

Nick Berardi
That is how I would do it if you can't write it in Perl.
Brad Gilbert
A: 

This will match the right part of the string, but won't tell you if it's two digits or three.

[^\d][\d]{2,3}[^\d]

Still, you could use that to grab the number, convert it to an int, add 10000, and convert that to the string you need.

Joel Coehoorn
+6  A: 

James is right that you want to use the Regex.Replace method that takes a MatchEvaluator argument. The match evaluator delegate is where you can take the numeric string you get in the match and convert it into a number that you can add 10,000 to. I used a lambda expression in place of the explicit delegate because its more compact and readable.

using System;
using System.Text.RegularExpressions;

namespace RenameAspxFile
{
    sealed class Program
    {
        private static readonly Regex _aspxFileNameRegex = new Regex(@"(\S+\.)(\d+)(\.aspx)", RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnoreCase);
        private static readonly string[] _aspxFileNames= {"Photo.123.aspx", "Photo.456.aspx", "BigPhoto.789.aspx"};

        static void Main(string[] args)
        {
            Program program = new Program();
            program.Run();
        }

        void Run()
        {
            foreach (string aspxFileName in _aspxFileNames)
            {
                Console.WriteLine("Renamed '{0}' to '{1}'", aspxFileName, AddTenThousandToPhotoNumber(aspxFileName));
            }
        }

        string AddTenThousandToPhotoNumber(string aspxFileName)
        {
            return _aspxFileNameRegex.Replace(aspxFileName, match => String.Format("{0}{1}{2}", match.Result("$1"), Int32.Parse(match.Result("$2")) + 10000, match.Result("$3")));
        }
    }
}
Dan Finucane
A: 

Found this question since I was trying to do something similar in Vim. Ill put the solution here.

:s/Photo\.\d\+\.aspx/\=Photo\.submatch(0)+10000\.aspx/g
Niall Murphy