简体   繁体   中英

How do I perform a csharp (or perl )substitution string change the variable for each ocurrence in loop ( regex)?

I want perform a loop with global replacement and the original subject string change, and contain previous replacements for each replace

please anyone help me

for example i want to use a chain

and replace like a editor that replace

 text match1 text match2

replace for

  text mathreplace1 "starting after first ocurrence " text match2

and starting after first ocurrence and change the string continually

so if I wanted a hypothetical case using the chain replaced the back by a lookbehind did not have any problem

in text editors each replacement is saved in the chain of operation

IN CONCLUSION

replace and continue the second replace stored the replace in the subject string of the operation

On until the last replacement

I hope you can understand me

i not have defined code just looking to implement a loop that makes variable the input string in each replacement ; so that i can operate a replacement with regex command but using a variable string with the same command for each replacement

==================================================

I mean that in an operation each time a command is applied regex the input string is used if I replace the first occurrence is used the chain input

if I replace the occurrence second again it is used the input string and the position followed the end of match ocurrence

I WISH

it is replaced the first string and then

the result of this operation is used as the new chain continuing in the position after the match ocurrence so on

I made a code snippet: http://rextester.com/RLPS43509

I think the code below is the simplest way to do it:

using System;
using System.Text.RegularExpressions;
using System.Text;

namespace Rextester
{
    public class Program
    {
        public static string replaceAsWithWhatever(string inputText)
        {
            StringBuilder sb = new StringBuilder();
            Regex rx = new Regex("as");

            int prior = 0;
            foreach (Match match in rx.Matches(inputText))
            {
                int i = match.Index;

                // copy the text not matched in between
                sb.Append(inputText.Substring(prior, i - prior));
                // [optional] prepend some text before match 
                sb.Append(" [before replacement] ");
                // replace match with something, possibly permutation of match
                sb.Append(" [replacement of " + match.ToString() + "] ");
                // append text after match
                sb.Append(" [after replacement] ");

                prior = i + match.Length;
            }
            // copy remaining string after all matches to stringbuilder
            sb.Append(inputText.Substring(prior, inputText.Length - prior));
            return sb.ToString();
        }

        public static void Main(string[] args)
        {
            // test cases
            Console.WriteLine(replaceAsWithWhatever("text before as between as whatever"));
            Console.WriteLine(replaceAsWithWhatever("sentence without matches"));
            Console.WriteLine(replaceAsWithWhatever("as"));
            Console.WriteLine(replaceAsWithWhatever("as ass ;)"));
        }
    }
}

In my previous answer, I assumed you wanted to be able to change the replacement while looping through the matches. However after rereading I think I understand what was asked.

My interpretation: Much like in C-preprocessor #define you want to unfold and match again.

Example replace /word/ with "echo wo" in string "wordrd" :

"wordrd" -> "echo word" -> "echo echo rd"

There is a serious problem here, if the replacement contains a match as well, you'd be looking at an infinite word.

Example: replace /ass/ with "assassin"

"ass" -> "assassin" -> "assassinassin" -> etc.

To avoid infinite loops/words, this solution checks the index of the last match in the replacement only, and uses the prior match + this offset as a minimum index. Basically:

Example: replace /ass/ with "assassin" in string "assass"

"assass" -> "assassinass" -> "assassinassassin"

Example replace /as/ with "ba"

"asss" -> "bass" -> "bbas" -> "bbba"

Code here: http://rextester.com/PSTV39802 and below

using System;
using System.Text.RegularExpressions;
using System.Text;

/* Basically a context-free replacement, minus the infinite words */
namespace Rextester
{
    public class Program
    {
        public static string replace(string inputText, Regex find, string replacement)
        {
            // to avoid a situation like the following: replace ass with assassin in string ass
            // "ass" -> "assassin" -> "assassinassin" -> etc.
            // it is only allowed to match after the last match in the replacement
            // aka. if we were to replace "ass" with "assassin a" in string "assss" we'd get           
            // "ass" -> "assassin ass" -> "assassin aassassin a"
            int countToSkipInReplacement = 0;
            int minimumIndex = 0;

            Match m;

            // first check if the replacement contains matches as well
            m = find.Match(replacement);
            if (m.Success)
            {
                while (m.Success)
                {
                    countToSkipInReplacement = m.Index + 1;
                    m = m.NextMatch();
                } 
            }

            while(true)
            {
                // uncomment to see all forms in between
                //Console.WriteLine(inputText);

                // find a match
                m = find.Match(inputText);

                // skip until the minimum index is found
                while (m.Success && m.Index < minimumIndex)
                    m = m.NextMatch();

                // if it has no further matches, return current string
                if (!m.Success)
                    return inputText;

                // glue a new inputText together with the contents before, the replacements and whatever comes after
                inputText = inputText.Substring(0, m.Index) + 
                            replacement + 
                            inputText.Substring(m.Index + m.Length, inputText.Length - (m.Index + m.Length));

                // make sure it doesn't go back and replace the text it just inserted again.
                minimumIndex = m.Index + countToSkipInReplacement;
            }
        }

        public static void Main(string[] args)
        {
            Regex rx = new Regex("as");

            Console.WriteLine(replace("text before ass between as whatever", rx, "a"));
            Console.WriteLine(replace("sentence without matches", rx, "a"));
            Console.WriteLine(replace("as", rx, "a"));
            Console.WriteLine(replace("as", rx, "as"));
            Console.WriteLine(replace("assss", rx, "ba"));
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM