【问题标题】:C# - Remove characters with regexC# - 使用正则表达式删除字符
【发布时间】:2017-08-01 18:21:39
【问题描述】:

我有一个文本文件,我需要删除一些尾随分隔符。文本文件如下所示:

string text = @"1|'Nguyen Van| A'|'Nguyen Van A'|39
                2|'Nguyen Van B'|'Nguyen| Van B'|39";
string result = @"1|'Nguyen Van A'|'Nguyen Van A'|39
                  2|'Nguyen Van B'|'Nguyen Van B'|39";

我想删除字符“|”在字符串“Nguyen Van | A”和“Nguyen | Van B”中

所以我认为最好的方法是进行正则表达式替换?谁能帮我解决这个正则表达式?

谢谢

【问题讨论】:

  • 所以你有一个用竖线分隔的文本文件,并且在引用条目时允许在条目中使用竖线?我理解正确吗?你也可以使用第三方库吗?
  • 我会手写而不是对抗正则表达式...最终它是一个简单的状态机。
  • BULK INSERT Product FROM 'D:\product.data' WITH ( FIELDTERMINATOR = '|', ROWTERMINATOR = '\n' ); 我使用 BULK INSERT SQL Server 导入文件,但在这些字段中有错误。批量加载数据转换错误(指定代码页的类型不匹配或无效字符)。
  • 亲爱的xanatos,目前,我在两个系统的数据接口中,所以一切都是自动导入/导出的。谢谢
  • @NguyễnQuang - 我现在也有点困惑。您是否在代码中执行此操作以准备批量插入文件?默认 FIELDQUOTE 字符为 ",因此您可能会遇到其他问题,而不仅仅是无关的管道字符?如果您写的问题说明实际问题而不是建议的解决方法,也许会更好,因为可能有更好的方法来解决它。

标签: c# regex


【解决方案1】:

正则表达式应该是:

(?<=^[^']*'([^']*'[^']*')*[^']*)\|

要使用多行...所以

var rx = new Regex(@"(?<=^[^']*'([^']*'[^']*')*[^']*)\|", RegexOptions.Multiline);

string text = @"1|'Nguyen Van| A'|'Nguyen Van A'|39

2|'阮文B'|'阮|范 B'|39";

string replaced = rx.Replace(text, string.Empty);

示例:http://ideone.com/PTdsg5

强烈建议反对使用它...解释原因...尝试理解正则表达式。如果你能理解它,那么你可以使用它:-)

我会编写一个简单的状态机来计数',并在计数的' 为奇数时替换|

【讨论】:

  • 因为 BULK INSERT 命令不接受这些记录。我需要在使用 BULK INSERT 之前对其进行清洁。 stackoverflow.com/questions/12902110/… 解决方案解决了我遇到的问题。但是,对于大文件数据,该过程会运行很长时间。你有更好的方法吗?如删除 char |内容以字符串 |' 开头结尾是字符串 '|而不是计数 ' 并替换 |当计数的 ' 是奇数时。
  • @NguyễnQuang - 您应该将此作为一个新问题发布,并确保发布相关代码(即您如何打开和解析文件、调用 regex.Replace 的位置以及您的情况写出新文件)到那个问题。
  • 感谢您在这里寻找解决方案:stackoverflow.com/questions/13305139/…
  • @NguyễnQuang - 请使用您正在使用的代码发布一个新问题。我假设您正在加载整个文件并将此正则表达式与多行模式一起使用。发布新问题,我可以发布答案来帮助您。
【解决方案2】:

您提到使用多行正则表达式花费的时间太长,并询问了状态机方法。所以这里有一些使用函数来执行操作的代码(注意,函数可能需要稍微清理一下,但它显示了这个想法并且比正则表达式运行得更快)。在我的测试中,使用不带多行的正则表达式,我可以在大约 34 秒内处理 1,000,000 行(在内存中,而不是写入文件)。使用状态机方法大约需要 4 秒。

string RemoveInternalPipe(string line)
{
    int count = 0;
    var temp = new List<char>(line.Length);
    foreach (var c in line)
    {
        if (c == '\'')
        {
            ++count;
        }
        if (c == '|' && count % 2 != 0) continue;
        temp.Add(c);
    }
    return new string(temp.ToArray());
};

File.WriteAllLines(@"yourOutputFile",
    File.ReadLines(@"yourInputFile").Select(x => RemoveInternalPipe(x)));

要将性能与Regex 版本(不带多行选项)进行比较,您可以运行以下代码:

var regex = new Regex(@"(?<=^[^']*'([^']*'[^']*')*[^']*)\|");
File.WriteAllLines(@"yourOutputFile",
    File.ReadLines(@"yourInputFile").Select(x => regex.Replace(x, string.Empty));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-07
    • 1970-01-01
    • 2011-06-02
    • 2011-05-13
    • 1970-01-01
    • 2019-02-16
    • 2018-01-26
    相关资源
    最近更新 更多