在 C# 中清除不需要的十六进制字符 with/without 正则表达式

Clearing unwanted hex characters with/without regex in c#

我必须以更好的方式从异常消息中清除十六进制字符。现在它可以手动替换字符,这看起来像这样彻底的灾难:

            var clearedStr = str.Replace(Convert.ToString((char)0x01), "")
            .Replace(Convert.ToString((char)0x02), "")
            .Replace(Convert.ToString((char)0x03), "")
            .Replace(Convert.ToString((char)0x04), "")
            .Replace(Convert.ToString((char)0x05), "")
            .Replace(Convert.ToString((char)0x06), "")
            .Replace(Convert.ToString((char)0x07), "")
            .Replace(Convert.ToString((char)0x08), "")
            .Replace(Convert.ToString((char)0x0B), "")
            .Replace(Convert.ToString((char)0x0C), "")
            .Replace(Convert.ToString((char)0x0E), "")
            .Replace(Convert.ToString((char)0x0F), "")
            .Replace(Convert.ToString((char)0x10), "")
            .Replace(Convert.ToString((char)0x11), "")
            .Replace(Convert.ToString((char)0x12), "")
            .Replace(Convert.ToString((char)0x13), "")
            .Replace(Convert.ToString((char)0x14), "")
            .Replace(Convert.ToString((char)0x15), "")
            .Replace(Convert.ToString((char)0x16), "")
            .Replace(Convert.ToString((char)0x17), "")
            .Replace(Convert.ToString((char)0x18), "")
            .Replace(Convert.ToString((char)0x19), "")
            .Replace(Convert.ToString((char)0x1a), "")
            .Replace(Convert.ToString((char)0x1b), "")
            .Replace(Convert.ToString((char)0x1c), "")
            .Replace(Convert.ToString((char)0x1d), "")
            .Replace(Convert.ToString((char)0x1e), "")
            .Replace(Convert.ToString((char)0x84), "")
            .Replace(Convert.ToString((char)0x86), "")
            .Replace(Convert.ToString((char)0x87), "")
            .Replace(Convert.ToString((char)0x88), "")
            .Replace(Convert.ToString((char)0x89), "");

例如十六进制字符的消息:

实际上我写了一个正则表达式,但它适用于像 0x1e 这样的十六进制字符,但不适用于它的等效字符:

但我需要找到这些字符,而不是等同于十六进制的字符:

"","'","ƒ","","","'","","š","^","‰","Š","‹"," Œ","","„", "†", "‡"

相同字符及其符号:

"RS:, PU1:', NBH:ƒ, US:, ESC:, PU2:', GS:, SCI: š, HTS: ^, HTJ: ‰, VTS: Š, PLD: ‹, PLU: Œ, SUB:, IND: „, SSA: †, ESA: ‡"

正则表达式是我写的:

http://regexstorm.net/tester?p=%5b0-9%5dx%5b0-9A-F%5d&i=0x1e+0x91+0x1c+0x83

此外,我需要涵盖所有此类字符,而不是一堆。

有时候,好的 foreach 是正确的方法。怎么样:

 private static readonly char[] CharsToReplace =
 {
     '\x02',
     '\x03',
     '\x04',
     '\x05',
     '\x06',
     '\x07',
     '\x08',
     '\x0B',
     '\x0C',
     '\x0E',
     '\x0F',
     '\x10',
     '\x11',
     '\x12',
     '\x13',
     '\x14',
     '\x15',
     '\x16',
     '\x17',
     '\x18',
     '\x19',
     '\x1a',
     '\x1b',
     '\x1c',
     '\x1d',
     '\x1e',
     '\x84',
     '\x86',
     '\x87',
     '\x88',
     '\x89',
 };

public static string ReplaceNonPrintables(string stringToProcess)
{
    StringBuilder buf = new StringBuilder(stringToProcess.Length);
    foreach (var c in stringToProcess)
    {
        if (!CharsToReplace.Contains(c))
        {
            buf.Append(c)
        }
    }

    return buf.ToString();
}

在进一步阅读之前,请看一下 Ryszard Czech 的 了解如何在不使用任何向后添加换行符的多余代码的情况下执行此操作


这可以通过替换字符串中的每个控制字符来实现,幸运的是正则表达式有答案:

var s = "a \nb" + Convert.ToString((char)0x1b) + Convert.ToString((char) 0x1e);
Regex.Replace(s, @"\p{C}+", String.Empty);

@"\p{C}+" 匹配所有控制字符。请注意,这也会匹配换行符 (\n),这意味着您的输出不会有任何换行符,如您在 this 示例中所见。如果你想保留你的换行符,你必须首先将你的字符串拆分成一个数组,每行 Regex.Replace ,然后再次将它们放在一起。像这样:

var lines = s.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
var sb = new StringBuilder();

foreach (var line in lines)
{
    sb.AppendLine(Regex.Replace(line, @"\p{C}+", String.Empty));
}

s = sb.ToString();

这会留下一个尾随换行符,可以像这样轻松删除它:

if (sb[sb.Length - 1] == '\n')
    sb.Remove(sb.Length - 1, 1);

在调用 sb.ToString() 之前执行此操作。 Here 是一个 dotnetfiddle 演示这个

作为,你可以使用\p{C}来匹配任何控制字符。

但是你不需要添加很多代码来减去一些你可能想要保留的字符,使用字符 class 减法:

var output = Regex.Replace(YourTextVariable, @"[\p{C}-[\t\r\n]]+", "");

这将匹配一个或多个不同于制表符、回车符 return 和换行符的控制字符。