【问题标题】:Regex help specific to SpamassassinSpamassassin 特有的正则表达式帮助
【发布时间】:2019-06-25 16:20:02
【问题描述】:

我正在尝试为社会安全号码创建过滤器并使用以下正则表达式:

\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

【问题讨论】:

    标签: regex perl spamassassin


    【解决方案1】:

    您的问题是 \b 在单词边界匹配,- 被认为是单词边界。你可以试试这样:

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

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

    【讨论】:

    • 您可能希望将(?:^|[-\d]) 用作开头表达式,并在末尾使用(?:$|[-\d]),以特别允许在任一端使用空字符串。您当前的表达式要求两边至少有一个(非破折号、非数字)字符。
    • @tripleee 你说得对。谢谢你接听!
    • 当然,我失去了否定,对此感到抱歉 - 你在两个地方都需要[^-\d]
    • sheepish look 这就是我复制粘贴所得到的。谢谢。
    • 此答案的正则表达式将匹配 a007-08-9056,我不知道是否需要。 单词边界由两个字符或一个字符和一个开头定义 -文件或文件结尾,因此您不能说“- 被视为单词边界”,因为它只是一个字符。它算作非单词字符,因此当且仅当它与单词字符(字母、数字或下划线;有关\b 的更详细定义,请参阅my answer)相邻时,它才是单词边界。跨度>
    【解决方案2】:

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

    (?<!\S)(?!000|666)[0-8][0-9]{2}-(?!00)[0-9]{2}-(?!0000)[0-9]{4}(?!\S)
    

    这指定模式之前没有非空格字符,之后也没有非空格字符。环视允许您在仍然匹配字符串的开头或结尾时指定它。

    【讨论】:

      【解决方案3】:
      \b(?<![.-])(?!000|666)[0-8][0-9]{2}-(?!00)[0-9]{2}-(?!0000)[0-9]{4}\b(?![.-])
      

      这与您的正则表达式相同,但它也排除了周围的破折号和点(随意添加到这些字符类,但确保破折号 (-) 始终位于末尾,否则它将创建范围)。

      \b 匹配一个分词符。您可能知道这一点,但这意味着它的一侧(之前或之后但不是两者)必须是单词字符(字母、数字或下划线),而另一侧(之后或之前但不是两者)必须 not 是一个单词字符(它可能是一个换行符或由于已到达字符串的开头/结尾而不存在)。你想要这个,但你也想排除更多的东西。因此:

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

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

      当我说“如果有”时,我指的是存在换行符、文件开头或文件结尾的可能性。这些都会满足这些负面的看法。

      另见full regex explanation, with examples, at regex101

      【讨论】:

        猜你喜欢
        • 2011-06-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多