应该在正则表达式中转义哪些文字字符?
Posted
技术标签:
【中文标题】应该在正则表达式中转义哪些文字字符?【英文标题】:What literal characters should be escaped in a regex? 【发布时间】:2011-07-25 22:33:56 【问题描述】:我刚刚编写了一个正则表达式,用于 php 函数 preg_match
,其中包含以下部分:
[\w-.]
匹配任何单词字符,以及减号和点。虽然它似乎在 preg_match 中工作,但我尝试将它放入一个名为 Reggy 的实用程序中,它抱怨 “char 类中的空范围”。反复试验告诉我,这个问题是通过转义减号,将正则表达式变成
来解决的[\w\-.]
既然原来的似乎在 PHP 中工作,我想知道为什么我应该或不应该转义减号,并且 - 因为点也是 PHP 中具有含义的字符 - 为什么我不需要转义点。我正在使用的实用程序是不是很傻,它是在使用另一种正则表达式方言还是我的正则表达式真的不正确?我只是幸运 preg_match 让我侥幸逃脱了吗?
【问题讨论】:
有什么理由不使用preg_quote
?
可能不会。但这不是我问这个问题的原因。我试图学习一些关于正则表达式的新知识,只是使用preg_quote
会产生完全相反的效果。 :)。我确实意识到我标记了这个 PHP,但我正在寻找一个可能适用于任何 PCRE 实现的答案。
我明白了。那么,我可以建议:github.com/php/php-src/blob/…
虽然它仍然没有“直接”告诉我什么和什么不应该逃避,以及为什么,但它确实提供了关于它的行为方式的所有答案。供参考,官方出处镜像:github.com/luvit/pcre2/tree/master/src
【参考方案1】:
虽然确实有some characters should be escaped in a regex,但您问的不是正则表达式,而是字符类。其中破折号是特殊的。
你可以把它放在课堂结束时,而不是逃避它,[\w.-]
【讨论】:
【参考方案2】:[\w.-]
.
通常表示任何字符,但[]
之间没有特殊含义
-
在[]
之间表示一个范围,除非它被转义或者[]
之间的第一个或最后一个字符
【讨论】:
在字符类中.
真的意味着“任何字符”吗? (即在括号之间)
@Pelle 这是真的。我只是在编辑答案。大多数答案都错了;-)【参考方案3】:
句号在字符类中失去其元意义。
-
在字符类中具有特殊含义。如果它没有放在方括号的开头或结尾,则必须对其进行转义。否则它表示一个字符范围(A-Z
)。
您触发了另一个特殊情况。 [\w-.]
有效,因为\w
不表示单个字符。因此,PCRE 不可能创建字符范围。 \w
可能是不连贯的符号类,因此没有可用于创建范围 Z till .
的结束字符。同样,句号.
将在\w
可以匹配的第一个ascii 字符a
之前。没有可构造的范围。因此-
工作而不为你逃跑。
【讨论】:
【参考方案4】:在许多正则表达式实现中,适用以下规则:
字符类中的元字符是:
^
(否定)
-
(范围)
]
(课程结束)
\
(转义字符)
所以这些都应该被转义。不过也有一些极端情况:
-
如果放在类的开头或结尾([abc-]
或 [-abc]
),则无需转义。在相当多的正则表达式实现中,当直接放置在范围 ([a-c-abc]
) 或简写字符类 ([\w-abc]
) 之后也不需要转义。这是你观察到的
^
在类的开头 not 时不需要转义:[^a]
表示除 a
之外的任何字符,[a^]
匹配 a
或 ^
,等于:[\^a]
]
如果是类中唯一的字符,则无需转义:[]]
匹配字符 ]
【讨论】:
非常全面的答案,谢谢。关于[]]
的一个问题:如果你的班级只有一个角色,为什么不指定为\]
? (即不在括号内)
@Pelle “为什么不”是另一个问题,无关紧要。 “有不止一种方法可以做到这一点”是 preg 发明者的座右铭;)
@Pelle,谢谢。没错,您可以(或应该?)简单地使用\]
而不是字符类,但我想提一下,许多正则表达式实现允许[]]
匹配文字]
。你甚至不需要转义]
,因为它只是字符类中的一个元字符。在它之外,只有[
需要从两个方括号中转义(但转义]
没有坏处!)。
用于包装/分隔正则表达式的字符必须进行转义,通常是'/'。
@AFAMed,这是一种语言限制,并非特定于正则表达式本身。【参考方案5】:
如果您使用 php 并且需要转义特殊的正则表达式字符,请使用 preg_quote
:
来自php.net的例子:
<?php
// In this example, preg_quote($word) is used to keep the
// asterisks from having special meaning to the regular
// expression.
$textbody = "This book is *very* difficult to find.";
$word = "*very*";
$textbody = preg_replace ("/" . preg_quote($word, '/') . "/",
"<i>" . $word . "</i>",
$textbody);
?>
【讨论】:
以上是关于应该在正则表达式中转义哪些文字字符?的主要内容,如果未能解决你的问题,请参考以下文章