如何转义 c# 拒绝转义的字符?

Lum*_*ous 0 c# regex

更新

在我看到“只需使用字符串文字!”之前 请注意,我正在尝试逃避角色()-_=+{[}|]。我认为正则表达式引擎不知道如何正确解析我的表达式。有一点我已经|]改变了]|,发现我的正则表达式只要有小写、大写和数字就可以传递所有内容。现在一切都失败了。我正在寻找的答案将解释我的正则表达式有什么问题。


我有这个正则表达式用于密码

^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[~`!@#$%^&*()-_=+{[}|]:\";'<>?,./\\])[^\r\n\t\f ]{8,16}$
Run Code Online (Sandbox Code Playgroud)

下面是 javascript 中等效的文字:

/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[~`!@#$%^&*()\-_=+{[}\]|:";'<>?,.\/\\])[^\r\n\t\f ]{8,16}$/
Run Code Online (Sandbox Code Playgroud)

javascript 表达式工作正常。至少 1 个小写字母、1 个大写字母、1 个数字、1 个特殊字符,且长度介于 8 到 16 个字符之间。

我的问题是我不知道如何转义组中的分组字符

(?=.*[~`!@#$%^&*()-_=+{[}|]:\";'<>?,./\\])
Run Code Online (Sandbox Code Playgroud)

具体来说,{[}|]部分。如果我尝试\[它会出错,但好的 ole MSDN却另有说明。

我在密码字段的验证属性中使用它

[RegularExpression("^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[~`!@#$%^&*()-_=+{[}|]:\";'<>?,./\\])[^\r\n\t\f ]{8,16}$", ErrorMessage = "Password must meet all specified criteria.")]
Run Code Online (Sandbox Code Playgroud)

Eri*_*ert 5

我正在寻找的答案将解释我的正则表达式有什么问题

这是你的正则表达式:

[RegularExpression(
  "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[~`!@#$%^&*()-_=+{[}|]:\";'<>?,./\\])[^\r\n\t\f ]{8,16}$"
Run Code Online (Sandbox Code Playgroud)

这是错误的。你想知道为什么它是错误的。让我们来分解一下。

首先,这是一个 C# 字符串文字。 它实际上代表什么字符?请记住,C# 字符串文字包含转义序列。这件事里的人物是:

^ ( ? = . * [ a - z ] ) ( ? = . * [ A - Z ] ) ( ? = . * 
\    -- this is the character represented by \\
d ) ( ? = . * [ ~ ` ! @ # $ % ^ & * ( ) - _ = + { [ } | ] :
"    -- this is the character represented by \"
; ' < > ? , . / 
\  -- this is the character represented by \\
] ) [ ^ 
<carriage return>   -- represented by \r
<newline>           -- represented by \n
<tabstop>           -- represented by \t
<feed>              -- represented by \f
<space>
] { 8 , 1 6 } $ 
Run Code Online (Sandbox Code Playgroud)

这些是字符串中的字符。它们代表您想要的正则表达式吗? 显然不是。该字符串包含正则表达式(为了清楚起见,我将在子表达式之间添加换行符):

^(?=.*[a-z])  -- right
 (?=.*[A-Z])  -- right
 (?=.*\d)     -- right
 (?=.*[~`!@#$%^&*()-_=+{[}|]:";'<>?,./\]) -- NOPE
 [^<carriage return><newline><tabstop><feed><space>] -- seems dodgy
 {8,16}$ -- right
Run Code Online (Sandbox Code Playgroud)

标记为 NOPE 的位显然是错误的。你想要什么字符串?你希望它是这组字符:

 (?=.*[~`!@#$%^&*()\-_=+{[}\]|:";'<>?,./\\])
Run Code Online (Sandbox Code Playgroud)

但它不是那组字符。现在你明白自己做错了什么了吗?

在 C# 常规字符串文字中,该字符集表示为:

 "(?=.*[~`!@#$%^&*()\\-_=+{[}\\]|:\";'<>?,./\\\\])"
Run Code Online (Sandbox Code Playgroud)

在 C# 逐字字符串文字中,该字符集表示为:

 @"(?=.*[~`!@#$%^&*()\-_=+{[}\]|:"";'<>?,./\\])"
Run Code Online (Sandbox Code Playgroud)

请注意,除了双双引号之外,逐字文字是逐字文字。由此得名。 在 C# 中构建正则表达式时使用逐字文字

另外,将来你应该通过尝试自己解决小子问题来解决此类问题。如果您尝试编写一个与单个 匹配的正则表达式[,那么您会更快地发现问题;如果您无法这样做,那么您关于如何这样做的问题会更容易回答。正则表达式是组合的;将问题分解为更小的问题,测试每个解决方案,然后将它们组合起来。如果你是这样进行的:

const string Lowercase = "(?=.*[a-z])";
const string Uppercase = "(?=.*[A-Z])";
const string Digits = "(?=.*\\d)";
const string Symbols = "(?=.*[~`!@#$%^&*()-_=+{[}|]:\";'<>?,./\\])"; // Wrong!
const string NoWhitespace = "[^\r\n\t\f ]"; // Dodgy!
const string Password = "^" + Lowercase + Uppercase + Digits + Symbols + NoWhitespace + "{8,16}$";
Run Code Online (Sandbox Code Playgroud)

那么您将拥有可用于单元测试的现成代码。当密码正则表达式失败时,您可以独立测试它的每个部分并找出问题所在,您可以尝试用仅匹配的表达式替换“符号”,[(然后进行调试。(还要注意我的版本是多么的自记录、可维护和清晰。它看起来仍然像调制解调器线路噪声,但至少它是不言自明的调制解调器线路噪声。)