繁体   English   中英

正则表达式不匹配一组字符串

[英]Regex not to match a set of Strings

如何构造一个不包含一组字符串的正则表达式。

对于此示例,我想验证地址行 1 文本框,使其不包含任何辅助地址部分,例如“Apt”、“Bldg”、“Ste”、“Unit”等。

正则表达式可用于验证字符串不包含一组单词。 这是一个经过测试的 Java 代码片段,带有注释的正则表达式,正是这样做的:

if (s.matches("(?sxi)" +
    "# Match string containing no 'bad' words.\n" +
    "^                # Anchor to start of string.\n" +
    "(?:              # Step through string one char at a time.\n" +
    "  (?!            # Negative lookahead to exclude words.\n" +
    "    \\b          # All bad words begin on a word boundary\n" +
    "    (?:          # List of 'bad' words NOT to be matched.\n" +
    "      Apt        # Cannot be 'Apt',\n" +
    "    | Bldg       # or 'Bldg',\n" +
    "    | Ste        # or 'Ste',\n" +
    "    | Unit       # or 'Unit'.\n" +
    "    )            # End list of words NOT to be matched.\n" +
    "    \\b          # All bad words end on a word boundary\n" +
    "  )              # Not at the beginning of bad word.\n" +
    "  .              # Ok. Safe to match this character.\n" +
    ")*               # Zero or more 'not-start-of-bad-word' chars.\n" +
    "$                # Anchor to end of string.")
    ) {
    // String has no bad words.
    System.out.print("OK: String has no bad words.\n");
} else {
    // String has bad words.
    System.out.print("ERR: String has bad words.\n");
} 

这假设单词必须是“完整的”单词,并且无论大小写都应该识别“坏”的单词。 另请注意,(正如其他人正确指出的那样),这不如简单地检查是否存在坏词然后采用逻辑非有效。

与其尝试构造一个正则表达式来匹配包含这些子字符串的字符串,为什么不构造一个正则表达式来匹配包含一个或多个子字符串的字符串 然后,如果该正则表达式返回true ,您就知道您有一个无效的字符串。

一个更理论的答案:

Deterministic Finite Automata 与正则表达式一一对应; 也就是说,对于每一种常规语言,您都可以构造一个 DFA,该 DFA 将完全接受常规语言中包含的字符串。 而且,对于每一种正则语言,您都可以构造一个正则表达式,它只匹配该语言中的字符串。 因此,对于任何正则表达式,您都可以构造一个接受完全相同字符串的 DFA,反之亦然。

通过为 NFA 中的每个状态组合构建 DFA state,可以将非确定性有限自动机 (NFA) 转换为确定性有限自动机 (DFA)。 (这是 |Q| 2个状态,这是一个有限数。)

有了这些知识,我们可以反转 DFA A并生成一个 DFA A' ,它接受A拒绝的每个字符串,并拒绝A接受的每个字符串。

这可以通过将所有结束状态转换为临时开始状态并将开始 state 转换为结束 state 来完成。 然后,我们继续将来自新的起始 state 的 epsilon-transitions 添加到这些临时启动状态中的每一个,以使其成为有效的 NFA(如果您想挑剔的话,请使用 epsilon-NFA)。 然后,我们将它变成我们知道的 DFA。

剩下的唯一步骤是将我们的新 DFA 转换为正则表达式。 这个算法非常简单:对于从开始状态到结束状态的每条路径,我们通过使用|将其包含在正则表达式中。 (或)每个分支,串行状态的连接,以及每个循环的* (kleene 闭包)。

你对你不想要的字符串进行否定 - 例如

"ten" !~ /one|two|three/

这给了你:

print "one" !~ /one|two|three/ --> false
print "two" !~ /one|two|three/ --> false
print "ten" !~ /one|two|three/ --> true

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM