2

我们需要限制字符串中的有效/允许字符。我们得到的规则如下:

  • 空格替换为下划线
  • 长度限制为 256(编译器限制)
  • 必须在 ASCII 码 32(空格)和 126(~)之间,并且...
  • 它不能包含以下任何内容:
    • : (冒号)
    • ; (分号)
    • ,(逗号)
    • '(单引号)
    • "(双引号)
    • \t(制表符)
    • \n (换行)
    • \r (回车)
    • \\(反斜杠)

任何不符合上述规则的内容都应替换为下划线。(我们可以简单地在最后修剪长度规则,除非 RegEx 中也有一些东西可以解决这个问题。)

现在我知道如何通过创建一个这样的类来说明允许的字符,比如字母数字字符......

[a-zA-Z0-9]

...然后在像这样的 Replace 调用中使用它的倒数(注意前导克拉)...

var cleanedString = RegEx.Replace(sourceString, "[^a-zA-Z0-9]", replacementString);

...但是我如何处理范围(“必须在 ' ' 和 '~' 之间”条件)以及特别排除的字符?您是否将其作为这样的“或”操作?

var cleanedString = RegEx.Replace(sourceString, @"[^ -~]|[;:,'""\t\n\r\\]", replacementString);

注意:这就是你在''(空格)和'~'之间开始一个范围的方式吗?不知道我是否必须以某种方式明确地逃离空间。

更一般地说,就像问题的标题所问的那样,说规则是它必须高于 32,但没有上限。你怎么能指定这样一个开放的范围?

4

3 回答 3

2

注意:以下实际上与要求相反 - 查找允许的字符。对于不允许的,是的,我会使用问题中引用的 OR 方法。

您可以使用减法字符类(在 Microsoft.NET 中支持 - 请注意,Mono 在处理减法字符类时显然存在 - 或曾经存在 - 错误):

版本 1

[\x21-\x7e-[\\:;,'"]]

解释:

  • [\x21-\x7e]= ASCII 33 (0x21) 和 126 (0x7e) 之间的字符。
  • -[\\:;,'"]= 除外\(转义)、:;、和.,'"

换句话说,-[...]在字符类中减去指定的字符。

该范围已经负责删除空格、制表符、回车和换行符,因此无需单独指定它们。

是的,作为替代方案,[\x20-\x7e]您可以使用[ -~]. 你不需要逃离这个空间。记住我们不想要空间,上面也可以写成:

版本 2

[!-~-[\\:;,'"]]

!(ASCII 33) 到~(ASCII 126),减去字符类中的字符除外。

实际上我认为我更喜欢版本 1 的可读性。

于 2013-07-09T23:06:57.110 回答
2

第 3 条规则识别的字符范围称为ASCII 可打印字符

您可以使用表达式[\x20-\x7E]

您也可以使用 Unicode 表达式\P{C}

POSIX 字符类 [:print:] 似乎合适,但似乎不受 .NET 正则表达式的支持;当我尝试它时它没有用。

参考: http ://www.regular-expressions.info/posixbrackets.html

更新:以下是针对整个 OP 所述问题的更多解决方案:

static string StripInvalidCharacters(string input)
{
    return new System.Text.RegularExpressions.Regex(@"\s|[:;,'""\\]|\p{C}").Replace(input, "_");
}

注意:实际上,您可能希望在此方法之外创建 Regex 对象,以避免每次调用此方法时都重新创建它。

我定义了一个符合以下条件的表达式:

  • 任何空格字符(空格、制表符、回车或换行符)
  • 其中之一:冒号、分号、逗号、单引号、双引号、反斜杠
  • 任何控制字符。请注意,我在表达式 \p{C} 中使用了小写 p 而不是我在上面在原始答案中提到的大写 P。这是因为大写的 P 否定了 {C} 部分,这意味着“所有控制字符”(参考:http: //msdn.microsoft.com/en-us/library/20bw873z.aspx)。所以表达式 \P{C} 基本上表示“任何不是控制字符的字符”,但在这个代码示例中,因为我用下划线替换字符,所以我想匹配“任何作为控制字符字符”,所以我为此使用了 \p{C} 表达式。
于 2013-07-09T21:51:56.240 回答
0

AFAIK 你只能在字符集(az,AZ,0-9)上做范围,而不是 ascii 表示的范围。

我相信解决这个问题的方法是将整个字符串转换为 acii,并在 (\&#[0-9]{2,3}\;) 上拆分匹配,然后测试每个。

从理论上讲,您可以编写一个明确匹配每个有效 256 长度可能性的正则表达式。不要以为你想要……这引出了一个问题,为什么首先要使用正则表达式?

于 2013-07-09T20:32:34.717 回答