Zath
Zath

Reputation: 557

C# Regex wildcard multiple replace

Doing a search for different strings using wildcards, such as doing a search for test0? (there is a space after the ?). The strings the search produces are:

test01 
test02 
test03 
(and so on)

The replacement text should be for example:

test0? - 

The wildcard above in test0? - represents the 1, 2, or 3...

So, the replacement strings should be:

test01 - 
test02 - 
test03 - 

string pattern = WildcardToRegex(originalText);
fileName = Regex.Replace(originalText, pattern, replacementText);

public string WildcardToRegex(string pattern)
{
    return "^" + System.Text.RegularExpressions.Regex.Escape(pattern).
        Replace("\\*", ".*").Replace("\\?", ".") + "$";
}

The problem is saving the new string with the original character(s) plus the added characters. I could search the string and save the original with some string manipulation, but that seems like too much overhead. There has to be an easier way.

Thanks for any input.

EDIT:

Search for strings using the wildcard ? Possible string are:
test01 someText
test02 someotherText
test03 moreText

Using Regex, the search string patter will be:
test0? -
So, each string should then read:
test01 - someText
test02 - someotherText
test03 - moreText

How to keep the character that was replaced by the regex wildcard '?'

As my code stands, it will come out as test? - someText
That is wrong.

Thanks.

EDIT Num 2

First, thanks everyone for their answers and direction. It did help and lead me to the right track and now I can better ask the exact question:
It has to do with substitution.

Inserting text after the Regex.

The sample string I gave, they may not always be in that format. I have been looking into substitution but just can't seem to get the syntax right. And I am using VS 2008.

Any more suggestions?

Thanks

Upvotes: 0

Views: 3790

Answers (4)

Jim Mischel
Jim Mischel

Reputation: 134025

If you want to replace "test0? " with "test0? -", you would write:

string bar = Regex.Replace(foo, "^test0. ", "$0- ");

The key here is the $0 substitution, which will include the matched text.

So if I understand your question correctly, you just want your replacementText to be "$0- ".

Upvotes: 2

Gustavo Azevedo
Gustavo Azevedo

Reputation: 113

You can catch any piece of your matched string and place anywhere in the replace statement, using symbol $ followed by the index of catched element (it starts at index 1).

You can catch element with parenthesis "()"

Example:

If I have several strings with testXYZ, being XYZ a 3-digit number, and I need to replace it, say, with testZYX, inverting the 3 digits, I would do:

string result = Regex.Replace(source, "test([0-9])([0-9])([0-9])", "test$3$2$1");

So, in your case, it can be done:

string result = Regex.Replace(source, "test0([0-9]) ", "test0$1 - ");

Upvotes: 0

Brad Christie
Brad Christie

Reputation: 101614

So I'm not 100% clear on what you're doing, but I'll give it a try.

I'm going with the assumption that you want to use "file wildcards" (?/*) and search for a set of values that match (while retaining the values stored using the placeholder itself), then replace it with the new value (re-inserting those placeholders). given that, and probably a lot of overkill (since your requirement is kind of weird) here's what I came up with:

// Helper function to turn the file search pattern in to a
// regex pattern.
private Regex BuildRegexFromPattern(String input)
{
    String pattern = String.Concat(input.ToCharArray().Select(i => {
        String c = i.ToString();
        return c == "?" ? "(.)"
            : c == "*" ? "(.*)"
            : c == " " ? "\\s"
            : Regex.Escape(c);
    }));
    return new Regex(pattern);
}

// perform the actual replacement
private IEnumerable<String> ReplaceUsingPattern(IEnumerable<String> items, String searchPattern, String replacementPattern)
{
    Regex searchRe = BuildRegexFromPattern(searchPattern);

    return items.Where(s => searchRe.IsMatch(s)).Select (s => {
        Match match = searchRe.Match(s);
        Int32 m = 1;
        return String.Concat(replacementPattern.ToCharArray().Select(i => {
            String c = i.ToString();
            if (m > match.Groups.Count)
            {
                throw new InvalidOperationException("Replacement placeholders exceeds locator placeholders.");
            }
            return c == "?" ? match.Groups[m++].Value
                : c == "*" ? match.Groups[m++].Value
                : c;
        }));
    });
}

Then, in practice:

String[] samples = new String[]{
    "foo01", "foo02 ", "foo 03",
    "bar0?", "bar0? ", "bar03 -",
    "test01 ", "test02 ", "test03 "
};

String searchTemplate = "test0? ";
String replaceTemplate = "test0? -";

var results = ReplaceUsingPattern(samples, searchTemplate, replaceTemplate);

Which, from the samples list above, gives me:

matched:      & modified to:

test01         test01 -
test02         test02 -
test03         test03 -

However, if you really want to save headaches you should be using replacement references. there's no need to re-invent the wheel. The above, with replacements, could have been changed to:

Regex searchRe = new Regex("test0(.*)\s");
samples.Select(x => searchRe.Replace(s, "test0$1-"));

Upvotes: 0

tmoore82
tmoore82

Reputation: 1875

If I understand the question correctly, couldn't you just use a match?

//Convert pattern to regex (I'm assuming this can be done with your "originalText")
Regex regex = pattern;

//For each  match, replace the found pattern with the original value + " -"
foreach (Match m in regex.Matches)
{
    RegEx.Replace(pattern, m.Groups[0].Value + " -");
}

Upvotes: 0

Related Questions