【问题标题】:Regex.Replace with large strings and backslashes正则表达式。用大字符串和反斜杠替换
【发布时间】:2013-11-27 08:23:53
【问题描述】:

我编写了一个实用程序,它打开一个基于文本的文件,加载为字符串并使用RegEx.Replace 执行查找/替换功能。

它对许多文件执行此操作,用户将其指向文件夹,输入查找字符串、替换字符串,然后文件夹中包含文件中字符串的所有文件都将被替换。

这很好用,直到我在它掉下来的地方用反斜杠尝试它。

很简单:

newFileContent = Regex.Replace(fileContent, @findString, @replaceString, RegexOptions.IgnoreCase);

fileContent = 基于文本的文件的内容。它将包含回车。

findString = 用户输入要查找的字符串

replaceString = 用户输入的字符串以替换找到的字符串

我尝试添加一些逻辑来反斜杠,如下所示,但这失败了,因为在模式结束时是非法的。

 if (culture.CompareInfo.IndexOf(findString, @"\") >= 0)
     {
      Regex.Replace(findString, @"\", @"\\");
     }

我需要做什么才能成功处理反斜杠,以便它们可以成为查找/替换逻辑的一部分?

下面的整个代码块。

//open reader
                using (var reader = new StreamReader(f,Encoding.Default)) 
                {
                    //read file
                    var fileContent = reader.ReadToEnd();

                    Globals.AppendTextToLine(string.Format(" replacing string"));

                    //culture find replace
                    var culture = new CultureInfo("en-gb", false);
                    //ensure nothing has changed
                    if (culture.CompareInfo.IndexOf(fileContent, findString, CompareOptions.IgnoreCase) >= 0)
                    {

                        //if find or replace string contains backslahes
                        if (culture.CompareInfo.IndexOf(findString, @"\") >= 0)
                        {
                            Regex.Replace(findString, @"\", @"\\");
                        }

                        //perform replace in new string
                        if (MainWindow.Main.chkIgnoreCase.IsChecked != null && (bool) MainWindow.Main.chkIgnoreCase.IsChecked)                        
                            newFileContent = Regex.Replace(fileContent, @findString, @replaceString, RegexOptions.IgnoreCase);
                        else
                            newFileContent = Regex.Replace(fileContent, @findString, @replaceString);

                        result[i].Result = true;
                        Globals.AppendTextToLine(string.Format(" success!"));
                    }
                    else
                    {
                        Globals.AppendTextToLine(string.Format(" failure!!"));
                        break;
                    }
                }

【问题讨论】:

  • 深思熟虑:如果我将一个文件放在一个大小超过您所拥有的内存量的文件夹中怎么办?目前您的解决方案将失败。也许您应该逐行替换,而不是一次替换整个文件。
  • 允许用户输入一个正则表达式字符串通常是一个坏主意,因为他们很容易在脚上开枪。一个例外可能是一个开发工具——用户应该事先知道它是一个正则表达式,并且有足够的知识来逃避他们的反斜杠。做一个正则表达式的外行是行不通的,你可能应该重新考虑你的方法。
  • 获取反馈,但它是技术帮助台的支持工具。

标签: c# regex


【解决方案1】:

当您将用户输入传递给Replace 方法时,您应该使用Regex.Escape

转义最小字符集(\、*、+、?、|、{、[、(,)、^、$、.、 # 和空格)通过用它们的转义码替换它们。这指示正则表达式引擎解释这些字符 字面意思而不是元字符。

例如:

newFileContent = Regex.Replace(fileContent,
                               Regex.Escape(findString),
                               replaceString,
                               RegexOptions.IgnoreCase);

【讨论】:

  • 出于兴趣 - 如果您要转义特殊字符,Regex.Replace 对 String.Replace 的“报价”是什么?
  • @tolanj:立即想到的主要好处是它允许您通过传递 RegexOptions.IgnoreCase 标志来执行不区分大小写的搜索。
  • 谢谢,我会发誓有一个内置的 String.Replace 至少需要一个 StringComparison,但实际上没有.. 似乎是一个常见的谬误stackoverflow.com/questions/5549426/…
  • 确实是忽略了迫使我使用正则表达式的案例
【解决方案2】:

您的基本问题是您让您的用户输入任意正则表达式,因此,它被解释为正则表达式......

你的目标是 just 替换文字字符串,在这种情况下使用 String.Replace 或者你 想要 允许用户输入正则表达式,在这种情况下只需接受用户需要 \ 转义他们的特殊字符。

因为 \ 是一个正则表达式转义字符(和 c# 一样,但你似乎正在用 @ 处理它)“\”是一个非法的正则表达式,因为 你在转义什么

如果您真的想要一个 rexexp 将所有 \ 替换为 \\ 那么它:

Regex.Replace(findString, @"\\", @"\\\\"); --ie one \ after escape, two chars after escape.

但是您仍然需要担心 [].?* 等。

我的强烈建议是一个复选框,用户可以选择是否输入正则表达式或字符串文字进行替换,然后相应地调用 String.Replace 或 Regex.Replace

【讨论】:

  • 一个很好的答案,因为您将 findhString 涵盖为正则表达式和文字,但如果它是文字,则只需转义元字符(包括 \ 本身)。 +1
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-14
  • 1970-01-01
  • 2010-11-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-27
相关资源
最近更新 更多