我如何执行 csharp(或 perl)替换字符串更改循环中每个发生次数的变量(正则表达式)

本文关键字:正则表达式 循环 变量 执行 何执行 csharp 字符串 替换 perl | 更新日期: 2023-09-27 17:55:08

我想执行全局替换循环和原始主题字符串更改,并包含每个替换的先前替换

请任何人帮助我

例如,我想使用链条

并像替换编辑器一样替换

 text match1 text match2

替换为

  text mathreplace1 "starting after first ocurrence " text match2

并在第一次出现后开始并不断更改字符串

因此,如果我想要一个使用链条的假设案例,请将背面替换为后视没有任何问题

在文本编辑器中,每个替换都保存在操作链中

结语

替换

并继续第二个替换将替换存储在操作的主题字符串中

打开直到最后一次更换

希望你能理解我

我没有定义代码,只是希望实现一个循环,使变量成为每次替换中的输入字符串;这样我就可以使用 regex 命令操作替换,但对每个替换使用具有相同命令的变量字符串

====

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

我的意思是,在每次应用正则表达式命令的操作中使用输入字符串如果我替换第一次出现是使用链输入

如果我再次替换出现次数,则使用输入字符串和位置,然后是匹配结束 ocurnce

但愿

它被替换第一个字符串,然后

此操作的结果用作新链赛后继续担任该位置等等

我如何执行 csharp(或 perl)替换字符串更改循环中每个发生次数的变量(正则表达式)

我做了一个代码片段:http://rextester.com/RLPS43509

我认为下面的代码是最简单的方法:

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 ;)"));
        }
    }
}

在我之前的回答中,我假设您希望能够在循环比赛时更改替换。但是,重读后,我想我明白了所问的内容。

我的解释:就像在 C 预处理器中一样#define您希望再次展开并匹配。

示例将字符串 "wordrd" 中的 /word/ 替换为 "echo wo"

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

这里有一个严重的问题,如果替换也包含匹配项,您将看到一个无限的单词。

示例:将/ass/替换为"assassin"

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

为了避免无限循环/单词,此解决方案仅检查替换中最后一个匹配项的索引,并使用前一个匹配项 + 此偏移量作为最小索引。基本上:

示例:将字符串"assass"中的/ass/替换为"assassin"

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

示例 将/as/替换为"ba"

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

此处的代码:http://rextester.com/PSTV39802 及以下

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"));
        }
    }
}