Regex 特定于Spamassassin的正则表达式帮助

Regex 特定于Spamassassin的正则表达式帮助,regex,perl,spamassassin,Regex,Perl,Spamassassin,我正在尝试为社会保险号码创建一个筛选器,并具有以下正则表达式: \b(?!000|666)[0-8][0-9]{2}-(?!00)[0-9]{2}-(?!0000)[0-9]{4}\b 问题是正则表达式还匹配Spamassassin中的以下类型的字符串,我还没有解决这个问题 18-007-08-9056-1462-2205 我希望它仅在SSN字符串独立时匹配。示例: 18 007-08-9056 1462-2205 007-08-9056 xyz 007-08-9056 007-08-9056

我正在尝试为社会保险号码创建一个筛选器,并具有以下正则表达式:

\b(?!000|666)[0-8][0-9]{2}-(?!00)[0-9]{2}-(?!0000)[0-9]{4}\b
问题是正则表达式还匹配Spamassassin中的以下类型的字符串,我还没有解决这个问题

18-007-08-9056-1462-2205

我希望它仅在SSN字符串独立时匹配。示例:

18 007-08-9056 1462-2205
007-08-9056
xyz 007-08-9056
007-08-9056 xyz

您的问题是
\b
在单词边界处匹配,
-
被视为单词边界。您可以尝试以下方法:

(?:^|[^-\d])((?!000|666)[0-8][0-9]{2}-(?!00)[0-9]{2}-(?!0000)[0-9]{4})(?:$|[^-\d])

然后将以
$1
的价格提供匹配项。您可能能够根据特定类型的输入字符串找到更优雅的解决方案。(例如,SSN周围是否总是有空格?如果是,您可以使用
\s
等)。

断言是一个单词边界-它匹配从单词字符转换为非单词字符的任何位置。数字是字字符,连字符不是。要指定空白边界,可以使用lookarounds:

(?<!\S)(?!000|666)[0-8][0-9]{2}-(?!00)[0-9]{2}-(?!0000)[0-9]{4}(?!\S)
(?
这指定模式前没有非空格字符,模式后没有非空格字符。环视允许您在字符串的开头或结尾仍然匹配的情况下指定此字符。

\b(?)?
\b(?<![.-])(?!000|666)[0-8][0-9]{2}-(?!00)[0-9]{2}-(?!0000)[0-9]{4}\b(?![.-])
这与正则表达式相同,但也排除了周围的破折号和点(可以随意添加到这些字符类中,但请确保破折号(
-
)始终位于末尾,否则它将创建一个范围)

\b
匹配分词符。您可能知道这一点,但这意味着分词符的一侧(在前面或后面,但不是两者)必须是单词字符(字母、数字或下划线),另一侧(在前面或后面,但不是两者)不能是单词字符(它可能是换行符或由于到达字符串的开头/结尾而不存在)。您希望这样做,但也希望排除其他一些内容。因此:

\b(?表示在单词中断后,检查前一个字符(如果有)。它不能与
[.-]
(点或破折号的单个字符)匹配

\b(?![.-])
表示在分词之后,下一个字符(如果有)必须与
[.-]
不匹配

当我说“如果有的话”时,我指的是可能有一个换行符、文件的开头或结尾,这些都会满足这些负面的条件


另请参见此

您可能希望对开头表达式使用
(?:^ |[-\d])
,并在结尾使用
(?:$|[-\d])
明确允许在任意一端使用空字符串。当前表达式要求至少有一个字符串(非破折号、非数字)两边都是字符。@tripleee你说得对。谢谢你抓住了!当然,我丢失了否定词,很抱歉-你想要
[^-\d]
两处都有。看起来很害羞,这就是我复制粘贴的结果。谢谢。这个答案的正则表达式将匹配
a007-08-9056
,我不知道是否需要。单词边界由两个字符或一个字符以及文件的开头或结尾定义,所以你不能说“
-
被认为是单词边界”因为它只是一个字符。它算作非单词字符,所以当且仅当它与单词字符(字母、数字或下划线;有关
\b
的更详细定义,请参阅)邻接时,它才是单词边界。