Double negative lookbehind in regex
我正在筛选包含特定人员ID的SQL脚本中的行。为了我的目的,最好是在过滤时过于热心,而不是在过滤下面,但我还是要小心一点。
例如,如果其中一个个人ID是
regex应该与以下每一行匹配:
1 2 3 | 123 [person_id] = 123 blah,blah,123,blah |
它不应该与每一行匹配:
1 2 | foo123bar [blob_id] = 123 |
号
我以为这个雷杰克斯会起作用:
1 | (?<!\[(?!person_id)\] = )\b123\b |
后面的外部负面评论说:"字符串不能以
不幸的是,情况似乎并非如此。它适用于除
我相信,由于某种原因,由于双重否定,背后的外表与任何事物都是匹配的。
这是我的regex101与我的测试用例的链接。
因为你过滤掉了整条线,这很容易:如果你在一条线上找到了任何你不想要的东西,你可以把这条线扔掉。
如果您正在使用PCRE,则可以使用回溯动词来实现您想要的目标:
1 | \bblob_id\b.+(*SKIP)(*FAIL)|\b123\b |
演示
如果regex引擎在一条线上遇到
在c中,您没有
1 | \bblob_id\b.+|(?<id>\b123\b) |
号
检查
但是在C中最好的选择是…要使用可变长度lookbehinds(C regex引擎的一个重要功能):
1 | \b123\b(?<!\bblob_id\b.*) |
演示
我将断言放在匹配之后只是为了优化,因此只有当引擎已经成功匹配
看来我误解了这个问题:
In your second demo, the only
that it filters out is blob_id . I need it to filter out any id that isn'tperson_id .
号
那么,在这种情况下,你需要把那些括号放回去,告诉我什么是ID,什么是其他东西。我想我可以利用它们,因为你在你的问题上确实做到了这一点。那么双重负面的环顾是有意义的:
1 2 | \b123\b(?<!\[(?!person_id\b)\w+\][^\] ]*) |
。
演示
]
这可能会更清楚地解释正在发生的事情,以及如何添加确定ID的列表,同时排除您定义的括号格式。
编辑-做断言的提示。断言是自包含的构造。他们的行动独立于彼此之间。断言不知道它们是否在另一个内部断言。给他们的位置是当前位置相对于呼叫者,这可能与最外面的不同当前位置。
最后,不管断言是什么,在断言内部,表达式必须匹配..这是首要规则。该匹配的成功或失败在逻辑上解析为断言它是,即负/正结果。
埃多克斯1〔9〕
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | .* # For testing purposes, get whole line before (?<! # Bracket ID's can't be behind the '123' \[ # Open bracket [ (?! # Exclude ID's that are OK to be here (?: person_id # this id is OK | ok_id # this id is OK (add more here, etc..) ) \] ) [^\]]+ # 1 or more id chars \] # Close bracket ] \s* # Optional whtiespace = # Equals sign \s* # Optional whtiespace ) \b 123 \b .* # For testing purposes, get whole line after |
。
代码段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | string input = @" 123 [person_id] = 123 blah,blah,123,blah foo123bar [blob_id] = 123 "; Regex Rx123 = new Regex(@".*(?<!\[(?!(?:person_id|ok_id)\])[^\]]+\]\s*=\s*)\b123\b.*"); Match _m = Rx123.Match( input ); while (_m.Success) { Console.WriteLine("Found: {0}", _m.Groups[0].Value); _m = _m.NextMatch(); } |
。
输出:
1 2 3 | Found: 123 Found: [person_id] = 123 Found: blah,blah,123,blah |
问题是
1 | (?<!(?<!\[person_id)\] = )\b123\b |
演示