如何使用正则表达式匹配连字符?

107
如何重写模式[a-zA-Z0-9!$* \t\r\n]以匹配连字符和现有字符?

你可以使用\s代替添加空格和\t。 \s也匹配其他类型的空白字符。 - Radu Simionescu
6个回答

232

连字符通常是正则表达式中的普通字符。只有当它在字符类中,并且位于两个其他字符之间时,才具有特殊含义。您可以转义字符类中的连字符,但不需要这样做。

因此:

  • - 匹配连字符。
  • [-] 匹配连字符。
  • [abc-] 匹配 abc 或 连字符。
  • [-abc] 匹配 abc 或 连字符。
  • [ab\-c] 匹配 abc 或 连字符。
  • [ab-d] 匹配 abcd(仅在此处连字符表示字符范围)。

如果连字符不能形成一个范围,它将从字符类中被当做字面量处理。请参考此链接:http://stackoverflow.com/questions/29458636/how-does-this-pattern-match-hyphen-without-escape。 - MAKZ
注意:如果您在代码中使用连字符的十六进制编码\x2D,它仍然会被视为表示字符范围(仅在JavaScript中测试过)。有其他人也发现了这个问题吗? - MarkP
2
@MarkP 嗯,显然:字符十六进制代码是由前端解析器(C#、JavaScript或其他语言)转换为实际字符的。因此,使用十六进制代码与使用实际字符在字符串值方面是相同的。 - Konrad Rudolph
@Puck 不需要括号。但是,正如答案所述,破折号必须放在最后。特别地,括号不会产生你期望的效果;你需要将它们(以及空格)删除。 - Konrad Rudolph
2
@Pshemo 当然,这是个愚蠢的错误。关于在 [a-c-e] 中的解释:在某些正则表达式规范/引擎中,这是无效的。例如,POSIX 正则表达式就不允许它。 - Konrad Rudolph
[%--] matches any character between % and - (inclusive). [--@] matches any character between - and @ (inclusive). The notation [%--@] is invalid as it is ambiguous. So a hyphen only is a hyphen if it is first or last in the group. So this is valid [--@%--] but this is not [%----@] - kvantour

78

转义连字符。

[a-zA-Z0-9!$* \t\r\n\-]

更新
不用在意这个答案 - 你可以在组中添加连字符,但不需要转义它。请查看Konrad Rudolph的答案,该答案回答得更好,并解释了原因。


哦,是吗?那是因为它在字符组里吗?我的错。 - Neil Barnwell
11
@KonradRudolph 您是正确的,但我不确定未转义版本更容易理解。破折号的两种可能用法令人困惑,这就是为什么一开始会有这样的问题。一旦您知道了它,它肯定更加优雅,但对于初学者来说有点令人困惑。 - Christophe Roussy
“Escape the hyphen.”这个答案我认为是误导性的,应该删除。正如@KonradRudolph所说:将其放在字符类的开头或结尾;否则它就没有特殊含义。如果保留这个答案,会让粗心或快速移动的工程师继续受到错误信息的影响。 - Ahmet

15

为了避免位置相关的问题,最好使用转义连字符。这是方括号字符类中的一个\-

但是还有其他要考虑的事情。一些列举的字符可能应该以不同的方式编写。在某些情况下,它们确实应该这样做。

此正则表达式风格的比较表明,C♯可以使用一些更简单的Unicode属性。如果你正在处理Unicode,你应该使用一般类别\p{L}表示所有可能的字母,以及可能的\p{Nd}表示十进制数字。此外,如果您想容纳所有的破折号标点,而不仅仅是HYPHEN-MINUS,则应使用\p{Pd}属性。 假设对于您来说这并不太普遍,您可能还希望将这个空白字符序列简单地写成\s

总的来说,这就是一个匹配该集合中任何一个字符的模式:[\p{L}\p{Nd}\p{Pd}!$*]

即使我没有打算处理完整的Unicode集合,我也可能会使用它,因为这是一个好习惯,而且因为这些东西经常超出其原始参数。现在,当您将其提升以在其他代码中使用时,它仍将正确工作。如果您硬编码所有字符,则不会。


我倾向于同意这个答案,你需要了解的越少,代码就越安全。这让我想起了运算符优先级的问题:http://stackoverflow.com/questions/10007140/operator-precedence-and-ternary-operator,我喜欢在它们中间加上括号(由我的IDE自动添加),不需要知道它们的全部内容。你或其他人可能会出错,迟早会出错。当然,如果你的项目中经常使用正则表达式,你可能需要更高级的知识。 - Christophe Roussy

6

[-a-z0-9]+,[a-z0-9-]+,[a-z-0-9]+以及[a-z-0-9]+都是相同的。两个范围之间的连字符被视为符号。并且[a-z0-9-+()]+这个正则表达式允许使用连字符。


这又为之前已有的众多答案增添了什么呢? - undefined

5
使用 "\p{Pd}"(不包括引号)来匹配任何类型的连字符。'-' 字符只是连字符的一种类型,它也恰好是正则表达式中的特殊字符。

3

您需要的是这个吗?

MatchCollection matches = Regex.Matches(mystring, "-");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接