用于排除特殊字符的正则表达式 [已关闭]

Regular expression for excluding special characters [closed]

提问人: 提问时间:4/16/2009 最后编辑:TylerH 更新时间:10/15/2023 访问量:316352

问:


想改进这个问题吗?更新问题,使其仅通过编辑这篇文章来关注一个问题。

4年前关闭。

我在想出一个正则表达式时遇到了麻烦,该表达式基本上会将某些特殊字符列入黑名单。

我需要使用它来验证输入字段中的数据(在 Java Web 应用程序中)。我们希望允许用户输入任何数字、字母(我们需要包括重音字符,例如法语或德语)和一些特殊字符,例如“-”。等。

如何将 <>%$ 等字符列入黑名单?

Java 正则表达式

评论

9赞 JohnFx 4/16/2009
我会把它放在评论中,因为它不是一个完整的解决方案,而只是一个建议。将字符列入白名单比将其列入黑名单要好得多,因为您想要允许的字符可能比拒绝的字符少得多。
0赞 Jason Coyne 4/16/2009
检查我更新的答案以使用 unicode 范围,也许这会简化白名单问题?
0赞 Jason Coyne 4/17/2009
在黑名单模式下,日本人、中国人、韩国人等都将被允许。这是可以接受的吗?

答:

5赞 Jason Coyne 4/16/2009 #1

通常最好将允许的字符列入白名单,而不是将不允许的字符列入黑名单。无论是从安全性的角度,还是从易于实施的角度来看。

如果你确实走黑名单路线,这里有一个例子,但请注意,语法并不简单。

http://groups.google.com/group/regex/browse_thread/thread/0795c1b958561a07

如果您想将所有重音字符列入白名单,也许使用 unicode 范围会有所帮助?查看此链接。

http://www.regular-expressions.info/unicode.html

评论

0赞 4/16/2009
感谢您的回复。我们首先尝试将白名单列入白名单,但这并不切实际,因为我们希望允许任何重音字符。我们从这个开始:^[a-zA-Z0-9。'-]+$ 然后我们必须手动添加所有法语字符。现在我们需要所有的德国人等等。
0赞 Lucero 4/16/2009
看看我的模式,它将所有字符列入白名单,包括所有重音字符。
0赞 BlairHippo 4/16/2009
根据 Gaijin 的链接,Lucero 的模式过于简单化;查看标有“Unicode 字符属性”的部分。(您需要像“\p{L}\p{M}*”这样的东西才能真正捕获所有重音字符。但我非常确定白名单是要走的路;一个完全填充的黑名单会受到伤害。
2赞 Lucero 4/16/2009 #2

您真的想将特定字符列入黑名单,还是将允许的字符列入白名单?

我假设你真的想要后者。这很简单(将任何其他符号添加到组中的白名单):[\-]

^(?:\p{L}\p{M}*|[\-])*$

编辑:使用注释中的输入优化了模式

评论

0赞 erickson 4/16/2009
这是正确的想法,但我认为不需要捕获组,或者在正确的地方。与该方法一起使用的“[-\p{L}]*”不是很好吗?matches()
0赞 Lucero 4/16/2009
是的,它应该。但是,我不确定 Java 正则表达式引擎如何准确处理 [-\p{L}];我至少会逃脱 - 角色。或者你可以创建一个非捕获组(这使得注册表不那么容易阅读):^(?:\p{L}|[\-])*$
0赞 BlairHippo 4/17/2009
请参阅 Gaijin 两个链接中的第二个链接,在“Unicode 字符属性”下——这可能无法捕获它需要的所有内容,具体取决于字符的编码方式。(该页面建议“\p{L}\p{M}*”。但绝对感觉它接近于解决方案。
0赞 Lucero 4/17/2009
这主要取决于字符串是否规范化,但是是的,这是一个有效的观点。
58赞 Daniel Brückner 4/16/2009 #3

我只会将角色列入白名单。

^[a-zA-Z0-9äöüÄÖÜ]*$

使用正则表达式构建黑名单同样简单,但您可能需要添加更多字符 - unicode 中有很多中文符号...... ;)

^[^<>%$]*$

表达式 [^(此处有许多字符)] 仅匹配未列出的任何字符。

评论

3赞 Lucero 4/16/2009
您的白名单模式只包含德语变音符号,但不包括法语或其他字符 - 并且有许多常见的字符......例如:ñëÿêâôîíì等。 因此,基本上只使用 Unicode 字符组就可以根据给定的要求将白名单列入白名单。
1赞 Daniel Brückner 4/16/2009
答案是肯定的。。。只有一个例子和变音符号最容易在德语键盘上打字。
4赞 Lucero 4/17/2009
你没有明白我想表达的观点。这不是关于你选择字符作为样本,而是关于无法真正将所有可能的组合列入白名单。
3赞 Jacob Krall 10/1/2009
@Atomiton,越南语(例如)有 11 个元音核,每个元音核可以有 5 个重音之一(例如:ệ)以及字母 đ。波兰语有 Ł Ź Ś Ę...土耳其语有虚线的 I、İ。有数百种不同的重音字母。
2赞 Daniel Brückner 10/1/2009
他想包括几百个,但他想排除几千个。
6赞 KarstenF 4/16/2009 #4

我想这取决于你针对的语言。一般来说,这样的事情应该有效:

[^<>%$]

“” 构造定义一个字符类,该类将与列出的任何字符匹配。将“”作为第一个字符将否定匹配,即:列出的字符之一以外的任何字符。[]^

您可能需要对 “” 中的某些字符进行转义,具体取决于您使用的语言/正则表达式引擎。[]

0赞 BlairHippo 4/16/2009 #5

我强烈怀疑,列出允许的字符和不允许的字符列表会更容易——一旦你有了这个列表,正则表达式语法就变得非常简单了。所以把我作为“白名单”的另一票。

11赞 David Grayson 4/16/2009 #6

要排除某些字符(<、>、% 和 $),您可以创建如下所示的正则表达式:

[<>%\$]

此正则表达式将匹配所有包含黑名单字符的输入。括号定义一个字符类,\ 在美元符号之前是必需的,因为美元符号在正则表达式中具有特殊含义。

要向黑名单添加更多字符,只需将它们插入括号之间即可;顺序无关紧要。

根据一些正则表达式的 Java 文档,您可以像这样使用表达式:

Pattern p = Pattern.compile("[<>%\$]");
Matcher m = p.matcher(unsafeInputString);
if (m.matches())
{
    // Invalid input: reject it, or remove/change the offending characters.
}
else
{
    // Valid input.
}

评论

0赞 Alan Moore 4/17/2009
如果正则表达式匹配整个字符串,则 matches() 返回 true,就好像它用 '^' 和 '$' 锚定在两端一样;您需要使用 find() 才能使此方法起作用。但是,请参阅其他答案,了解为什么黑名单是个坏主意。
0赞 Alan Moore 4/17/2009
此外,大多数元字符在字符类中时会失去其特殊含义,因此无需转义“$”。但是,如果您确实需要转义它,则必须使用两个反斜杠(“\\$”),因为它位于 Java String 文字中。
0赞 Sanshayan 11/3/2018
@How从字符串中删除这些字符,“replaceAll” mehtod 正在从字符串中删除有效字符
1赞 DJClayworth 4/17/2009 #7

为什么您认为正则表达式是最好的工具?如果您的目的是检测字符串中是否存在非法字符,则测试循环中的每个字符将比构造正则表达式更简单、更高效。

评论

0赞 Patanjali 11/30/2015
HTML 输入字段的 pattern 属性被设计为采用正则表达式,那么为什么要编写一个程序来做同样的事情呢?
1赞 Armstrongest 10/1/2009 #8

以下是所有法语重音字符: àÀâÂäÄáÁéÉèÈêÊëËÌÌîÎïÏòÒôÔöÖùÛÛüÜçÇ'ñ

我会在谷歌上搜索德语重音字符列表。没有那么多。你应该能够得到它们。

对于 URL,我将重音 URL 替换为常规字母,如下所示:

string beforeConversion = "àÀâÂäÄáÁéÉèÈêÊëËìÌîÎïÏòÒôÔöÖùÙûÛüÜçÇ’ñ";
string afterConversion = "aAaAaAaAeEeEeEeEiIiIiIoOoOoOuUuUuUcC'n";
for (int i = 0; i < beforeConversion.Length; i++) {

     cleaned = Regex.Replace(cleaned, beforeConversion[i].ToString(), afterConversion[i].ToString());
}

请注意,可能还有一种更有效的方法。

评论

1赞 Patanjali 11/28/2015
请注意,OP仅使用法语和德语作为示例,而不是作为详尽的清单,而没有说明清单有多大。许多人认为他们在要求黑名单时是错误的。
8赞 Patanjali 11/28/2015 #9

即使在 2009 年,似乎也有太多人对万维网的设计内容非常有限。在 2015 年,除非针对特定国家/地区进行设计,否则黑名单是容纳大量可能有效的字符的唯一方法。

然后,需要根据需要数据的目的选择要列入黑名单的字符。

但是,有时分解需求并单独处理每个需求是值得的。在这里,向前看是你的朋友。这些是以正和负为边界的部分,实际上成为 AND 块,因为当处理块时,如果没有失败,正则表达式处理器将从文本的开头开始下一个块。实际上,每个 look-ahead 块前面都会有 ,如果其模式是贪婪的,则最多包括 。即使是古老的 VB6/VBA (Office) 5.5 正则表达式引擎也支持前瞻。(?=)(?!)^$

因此,要构建一个完整的正则表达式,请从前瞻块开始,然后在最终的 .$

例如,要限制字符总数(包括 3 到 15 个字符),请从 positive look-ahead 块开始。请注意,这需要它自己的,并确保它涵盖所有文本。(?=^.{3,15}$)^$

现在,虽然您可能希望允许 _ 和 -,但您可能不希望以它们开头或结尾,因此请添加两个否定的 look-ahead 块,分别用于 start 和 ends。(?!^[_-].+)(?!.+[_-]$)

如果不需要多个 和 ,请添加负前瞻块 。这也将排除 和 序列。_-(?!.*[_-]{2,})_--_

如果没有更多的前瞻块,则在 之前添加黑名单块,例如 ,其中排除 null 和控制字符,包括 NL () 和 CR ()。最后确保所有文本都被贪婪地包含在内。$[^<>[\]{\}|\\\/^~%# :;,$%?\0-\cZ]+\0-\cZ\n\r+

在Unicode域中,可能还需要排除其他代码点或块,但肯定比必须包含在白名单中的所有块要少得多。

然后,上述所有内容的整个正则表达式将是

(?=^.{3,15}$)(?!^[_-].+)(?!.+[_-]$)(?!.*[_-]{2,})[^<>[\]{}|\\\/^~%# :;,$%?\0-\cZ]+$

您可以在 https://regex101.com/ 上实时查看 PCRE (PHP)、JAVASCRIPT 和 Python 正则表达式引擎。我不知道 java 正则表达式适合其中的位置,但您可能需要修改正则表达式以迎合其特性。

如果要包含空格,但不想包含空格,只需在正则表达式中的每个位置交换它们即可。_

这种技术最有用的应用是HTML字段的属性,其中需要单个表达式,如果失败,则返回false,从而使字段无效,允许css突出显示它,并停止提交表单。请注意,属性中的任何隔离(不在范围内)都必须具有前面才能对其进行转义。patterninputinput:invalid-pattern\

评论

0赞 Patanjali 11/28/2015
在提供包含正则表达式的答案时,请注意,某些字符(如 _ 和 *)可能会在答案文本的最终呈现中消失。在这种情况下,请在它们前面加上 \。有时,只有字符的第一次出现可能需要 \ 来确保所有该字符都显示在正则表达式中。它不一致,因此请在键入时注意呈现的文本,并根据需要添加 \。
0赞 Patanjali 11/29/2015
@Mariano。您显然已经编辑了我的答案以突出显示正则表达式,但您显然没有阅读我上面的评论,即需要插入一些 \,以便每个后面的字符可见。您的编辑已留在现在不必要的 \s 中。我现在将把它们编辑掉。如果您要弄乱答案,请进行完整编辑,或者不理会它们。
0赞 Patanjali 11/29/2015
@Mariano。你离开了四个\,我现在已经消除了。你是对的,因为第二次展望是不正确的。我的错,因为我已经为开始 _- 解决了它,但后来想起了尾随的,并在没有测试的情况下进行了临时编辑。在当时的第三次展望中,你对尾随的“.*”也是正确的。另外,关于开始^。帽子戏法!
0赞 Patanjali 11/29/2015
@Mariano。你去哪里了?这就是我所说的游击编辑!
1赞 Patanjali 11/30/2015
@Mariano。德摩根定理在行动!但是,并不总是能够在外部选择负数,尤其是在需要输出逻辑一致性的情况下。能够在一个表达式中获得正匹配,包括长度,这意味着它可以用于 HTML 输入文本字段中的 pattern 属性,我怀疑这将被大量使用。
0赞 Dharmender Tuli 9/12/2017 #10

使用这个

^(?=[a-zA-Z0-9~@#$^*()_+=[\]{}|\\,.?: -]*$)(?!.*[<>'"/;`%])
6赞 MCGRAW 1/24/2018 #11

ASCII 字符的非字母数字和下划线的否定集合:

/[^\W]/g

对于电子邮件或用户名验证,我使用了以下表达式,该表达式允许 4 个标准特殊字符 - _ .@

/^[-.@_a-z0-9]+$/gi

对于严格的仅字母数字表达式,请使用:

/^[a-z0-9]+$/gi

测试 @ RegExr.com

评论

1赞 Patanjali 1/26/2018
《任择议定书》的要求是能够包括其他语文。 并且只处理 ASCII。此外,除非在某个范围内使用,否则必须在术语中排在最后。\w\W-[]
0赞 MCGRAW 1/27/2018
@patanjali /^[-.@_a-z0-9]+$/gi 毫无疑问,这是有效的。
0赞 Patanjali 1/28/2018
每天学习新东西:可以在表达式的开头或结尾,这是有道理的。但是,无法处理.要真正处理多语言文本,必须使用原子表达式,例如匹配字母和数字。-[]/[^\W]/á\p{Ll}\p{M}*\p{N}
0赞 Patanjali 3/28/2018
对于我上面的评论,它应该是处理任何案例信。给定的用于小写。\p{L}\p{M}*