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

时间:2011-04-29 16:56:37

标签: java regex

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

对于这个例子,我想验证地址行1文本框,以便它不包含任何辅助地址部分,如'Apt','Bldg','Ste','Unit'等。

4 个答案:

答案 0 :(得分:5)

可以使用正则表达式来验证字符串是否包含一组单词。这是一个经过测试的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");
} 

这假设单词必须是“整个”单词,并且无论如何都应该识别“坏”单词。另请注意,(正如其他人已经正确说明的那样),这不如仅仅检查坏词的存在然后采用逻辑NOT那样有效。

答案 1 :(得分:0)

为什么不构造正则表达式来匹配包含一个或多个字符串的字符串,而不是尝试构造正则表达式以匹配包含这些子字符串的字符串他们?然后,如果该正则表达式返回true,则表示您的字符串无效。

答案 2 :(得分:0)

更理论的答案:

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

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

根据这些知识,我们可以撤消DFA A并生成DFA A',该{DAL A接受A拒绝的每个字符串,并拒绝|接受的每个字符串。

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

唯一剩下的步骤是将我们的新DFA变成正则表达式。对此的算法非常简单:对于从开始到结束状态的每条路径,我们在正则表达式中包含*(或)用于每个分支,串联状态的连接和{{1}}(每个循环都有kleene闭包。

答案 3 :(得分:-1)

你否定了你不想要的字符串 - 例如

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

这会给你:

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