正则表达式除了特定的单词

时间:2009-12-01 13:00:31

标签: regex exception words

我有正则表达式的问题。 除了一组指定的单词外,我需要制作正则表达式,例如:apple,orange,juice。 并且给出这些词语,它将匹配除上述词语之外的所有内容。

apple (should not match)
applejuice (match)
yummyjuice (match)
yummy-apple-juice (match)
orangeapplejuice (match)
orange (should not match)
juice (should not match)
orange-apple-juice (match)
apple-orange-aple (match)
juice-juice-juice (match)
orange-juice (match)

6 个答案:

答案 0 :(得分:9)

如果你真的想用一个正则表达式来做这件事,你可能会发现外观很有用(在这个例子中尤其是负向前瞻)。为Ruby编写的正则表达式(一些实现具有不同的外观语法):

rx = /^(?!apple$|orange$|juice$)/

答案 1 :(得分:3)

我注意到apple-juice应根据您的参数匹配,但apple juice怎么办?我假设如果你要验证apple juice,你仍然希望它失败。

所以 - 让我们构建一组算作“边界”的字符:

/[^-a-z0-9A-Z_]/        // Will match any character that is <NOT> - _ or 
                        // between a-z 0-9 A-Z 

/(?:^|[^-a-z0-9A-Z_])/  // Matches the beginning of the string, or one of those 
                        // non-word characters.

/(?:[^-a-z0-9A-Z_]|$)/  // Matches a non-word or the end of string

/(?:^|[^-a-z0-9A-Z_])(apple|orange|juice)(?:[^-a-z0-9A-Z_]|$)/ 
   // This should >match< apple/orange/juice ONLY when not preceded/followed by another
   // 'non-word' character just negate the result of the test to obtain your desired
   // result.

在大多数正则表达式中,\b计为“单词边界”,但“单词字符”的标准列表不包括-,因此您需要创建自定义单词。如果您还没有尝试抓住/\b(apple|orange|juice)\b/,它可以与-匹配...

如果您只是测试“单字”测试,您可以更简单地使用:

/^(apple|orange|juice)$/ // and take the negation of this...

答案 2 :(得分:0)

这有一些方法:

((?:apple|orange|juice)\S)|(\S(?:apple|orange|juice))|(\S(?:apple|orange|juice)\S)

答案 3 :(得分:0)

\A(?!apple\Z|juice\Z|orange\Z).*\Z

将匹配整个字符串,除非它只包含一个禁用词。

或者,如果您没有使用Ruby,或者您确定您的字符串不包含换行符,或者您设置了^$在开头/结尾不匹配的选项行

^(?!apple$|juice$|orange$).*$

也可以。

答案 4 :(得分:0)

这里有一些简单的复制粘贴代码,其作用不仅限于精确单词例外。


复制/粘贴代码:

在以下正则表达式中,仅将全部大写部分替换为您的正则表达式。

Python正则表达式
pattern = r"REGEX_BEFORE(?>(?P<exceptions_group_1>EXCEPTION_PATTERN)|YOUR_NORMAL_PATTERN)(?(exceptions_group_1)always(?<=fail)|)REGEX_AFTER"
Ruby正则表达式
pattern = /REGEX_BEFORE(?>(?<exceptions_group_1>EXCEPTION_PATTERN)|YOUR_NORMAL_PATTERN)(?(<exceptions_group_1>)always(?<=fail)|)REGEX_AFTER/
PCRE正则表达式
REGEX_BEFORE(?>(?<exceptions_group_1>EXCEPTION_PATTERN)|YOUR_NORMAL_PATTERN)(?(exceptions_group_1)always(?<=fail)|)REGEX_AFTER
的JavaScript

从2020年6月17日起是不可能的,并且在不久的将来将不可能。



完整示例

REGEX_BEFORE = \ b
YOUR_NORMAL_PATTERN = \ w +
REGEX_AFTER =
EXCEPTION_PATTERN =(苹果|橙色|果汁)

Python正则表达式
pattern = r"\b(?>(?P<exceptions_group_1>(apple|orange|juice))|\w+)(?(exceptions_group_1)always(?<=fail)|)"
Ruby正则表达式
pattern = /\b(?>(?<exceptions_group_1>(apple|orange|juice))|\w+)(?(<exceptions_group_1>)always(?<=fail)|)/
PCRE正则表达式
\b(?>(?<exceptions_group_1>(apple|orange|juice))|\w+)(?(exceptions_group_1)always(?<=fail)|)



它如何工作?

这使用了相当复杂的正则表达式,即原子组,条件,后向和命名组。

  1. (?>是原子组的开始,这意味着它不允许回溯:这意味着,如果该组匹配一次,但后来由于后向失败而无效,则整个组将不匹配。 (在这种情况下,我们希望这种行为)。

  2. (?<exceptions_group_1>创建一个命名的捕获组。它比使用数字更容易。请注意,该模式首先尝试查找异常,然后在找不到异常的情况下退回到普通模式。

  3. 请注意,原子模式首先尝试查找异常,然后在找不到异常的情况下返回常规模式。

  4. 真正的魔力在(?(exceptions_group_1)中。这是有条件的询问exceptions_group_1是否成功匹配。如果是,那么它将尝试查找always(?<=fail)。这种模式(如它所说)将始终失败,因为它会寻找“始终”一词,然后检查“是否会“一直” =“失败””,这是永远不会失败的。

  5. 因为有条件的失败,这意味着原子组失败,并且因为它是原子的,这意味着其已经匹配了异常,因此不允许其回溯(试图查找正常模式)。

这绝对不是打算使用这些工具的方式,但它应该可靠且有效地工作。



对Ruby中原始问题的确切答案

/\b(?>(?<exceptions_group_1>(apple|orange|juice))|\w+)(?(<exceptions_group_1>)always(?<=fail)|)/

与其他方法不同,可以修改此方法以拒绝任何模式,例如不包含子字符串“ apple”,“ orange”或“ juice”的任何单词。

/\b(?>(?<exceptions_group_1>\w*(apple|orange|juice))|\w+)(?(<exceptions_group_1>)always(?<=fail)|)/

答案 5 :(得分:-1)

类似(PHP)

$input = "The orange apple gave juice";
if(preg_match("your regex for validating") && !preg_match("/apple|orange|juice/", $input))
{
  // it's ok;
}
else
{
  //throw validation error
}