【问题标题】:Multiple string replace in c#c#中的多个字符串替换
【发布时间】:2012-07-31 08:49:41
【问题描述】:

我正在动态编辑一个正则表达式以匹配 pdf 中的文本,它可以在某些行的末尾包含连字符。

例子:

源字符串:

"consecuti?vely"

替换规则:

 .Replace("cuti?",@"cuti?(-\s+)?")
 .Replace("con",@"con(-\s+)?")
 .Replace("consecu",@"consecu(-\s+)?")

期望的输出:

"con(-\s+)?secu(-\s+)?ti?(-\s+)?vely"

替换规则是动态构建的,这只是一个导致问题的例子。

执行这种多重替换的最佳解决方案是什么,这将产生所需的输出?

到目前为止,我考虑过使用 Regex.Replace 并压缩单词以替换为可选 (-\s+)?在每个字符之间,但这不起作用,因为要替换的单词在正则表达式上下文中已经包含特殊含义的字符。

编辑:我当前的代码,当替换规则重叠时不起作用,如上例所示

private string ModifyRegexToAcceptHyphensOfCurrentPage(string regex, int searchedPage)
    {
        var originalTextOfThePage = mPagesNotModified[searchedPage];
        var hyphenatedParts = Regex.Matches(originalTextOfThePage, @"\w+\-\s");
        for (int i = 0; i < hyphenatedParts.Count; i++)
        {
            var partBeforeHyphen = String.Concat(hyphenatedParts[i].Value.TakeWhile(c => c != '-'));

            regex = regex.Replace(partBeforeHyphen, partBeforeHyphen + @"(-\s+)?");
        }
        return regex;
    }

【问题讨论】:

  • 我很难从您的示例中看到一组明确的规则。我假设这种连字符可以发生在任何字符串上,因此,您显示的示例仅特定于该字符串。您需要提供更多关于如何构建正则表达式的一般规则。
  • 这是本示例的最终规则集。我扫描 pdf 页面以查找模式 word-hyphen-newline 并获取所有带连字符的字符串。在这种情况下,它只产生了上面的 3 条规则。
  • 抱歉,您所说的与您的示例不符 1) ? 不是连字符,2) 没有新行。那么你是说每个单独的字符串都有特定的规则吗?
  • 我会将我当前的代码放在问题中。这适用于替换规则不重叠的所有情况。

标签: c# regex


【解决方案1】:

这个程序的输出是 "con(-\s+)?secu(-\s+)?ti?(-\s+)?vely"; 据我了解您的问题,我的代码可以完全解决您的问题。

class Program
    {
        class somefields
        {
            public string first;
            public string secound;
            public string Add;
            public int index;
            public somefields(string F, string S)
            {
                first = F;
                secound = S;
            }

        }
    static void Main(string[] args)
    {
        //declaring output
        string input = "consecuti?vely";
        List<somefields> rules=new List<somefields>();
        //declaring rules
        rules.Add(new somefields("cuti?",@"cuti?(-\s+)?"));
        rules.Add(new somefields("con",@"con(-\s+)?"));
        rules.Add(new somefields("consecu",@"consecu(-\s+)?"));
        // finding the string which must be added to output string and index of that
        foreach (var rul in rules)
        {
            var index=input.IndexOf(rul.first);
            if (index != -1)
            {
                var add = rul.secound.Remove(0,rul.first.Count());
                rul.Add = add;
                rul.index = index+rul.first.Count();
            }

        }
        // sort rules by index
        for (int i = 0; i < rules.Count(); i++)
        {
            for (int j = i + 1; j < rules.Count(); j++)
            {
                if (rules[i].index > rules[j].index)
                {
                    somefields temp;
                    temp = rules[i];
                    rules[i] = rules[j];
                    rules[j] = temp;
                }
            }
        }

        string output = input.ToString();
        int k=0;
        foreach(var rul in rules)
        {
            if (rul.index != -1)
            {
                output = output.Insert(k + rul.index, rul.Add);
                k += rul.Add.Length;
            }
        }
        System.Console.WriteLine(output);
        System.Console.ReadLine();
    }
} 

【讨论】:

  • 这个想法很好,但是当单个替换规则出现多次时,它就行不通了。
  • 还有一个冒泡排序+1,让我笑了:))
  • 可以在循环中添加规则,然后在循环后全部执行。
【解决方案2】:

您可能应该编写自己的解析器,它可能更容易维护:)。

如果字符串不包含它,也许您可​​以在模式周围添加“特殊字符”以便像“##”一样保护它们。

【讨论】:

  • 如果没有人提供简单的解决方案,那就是计划:(
  • 我基本上会做一个 Aho-Corasick 搜索机,它会跳过特殊含义的字符,而不是报告找到的字符串,我会插入我的替换序列 @(-\s+)?
【解决方案3】:

试试这个:

var final = Regex.Replace(originalTextOfThePage, @"(\w+)(?:\-[\s\r\n]*)?", "$1");

【讨论】:

    【解决方案4】:

    我不得不放弃一个简单的解决方案,自己编辑了正则表达式。作为副作用,新方法只通过字符串两次。

    private string ModifyRegexToAcceptHyphensOfCurrentPage(string regex, int searchedPage)
        {
            var indexesToInsertPossibleHyphenation = GetPossibleHyphenPositions(regex, searchedPage);
            var hyphenationToken = @"(-\s+)?";
            return InsertStringTokenInAllPositions(regex, indexesToInsertPossibleHyphenation, hyphenationToken);
        }
    
        private static string InsertStringTokenInAllPositions(string sourceString, List<int> insertionIndexes, string insertionToken)
        {
            if (insertionIndexes == null || string.IsNullOrEmpty(insertionToken)) return sourceString;
    
            var sb = new StringBuilder(sourceString.Length + insertionIndexes.Count * insertionToken.Length);
            var linkedInsertionPositions = new LinkedList<int>(insertionIndexes.Distinct().OrderBy(x => x));
            for (int i = 0; i < sourceString.Length; i++)
            {
                if (!linkedInsertionPositions.Any())
                {
                    sb.Append(sourceString.Substring(i));
                    break;
                }
                if (i == linkedInsertionPositions.First.Value)
                {
                    sb.Append(insertionToken);
                }
                if (i >= linkedInsertionPositions.First.Value)
                {
                    linkedInsertionPositions.RemoveFirst();
                }
                sb.Append(sourceString[i]);
            }
            return sb.ToString();
        }
    
        private List<int> GetPossibleHyphenPositions(string regex, int searchedPage)
        {
            var originalTextOfThePage = mPagesNotModified[searchedPage];
            var hyphenatedParts = Regex.Matches(originalTextOfThePage, @"\w+\-\s");
            var indexesToInsertPossibleHyphenation = new List<int>();
            //....
            // Aho-Corasick to find all occurences of all 
            //strings in "hyphenatedParts" in the "regex" string
            // ....
            return indexesToInsertPossibleHyphenation;
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-08
      • 1970-01-01
      • 1970-01-01
      • 2016-09-10
      • 1970-01-01
      相关资源
      最近更新 更多