Perl Regex 负后视不正确匹配 (SAS)

Perl Regex Negative Lookbehind Incorrect Match (SAS)

在 SAS 中,我正在设置 PXPARSE 函数以从调查的自由文本答案中提取有意义的信息。在大多数情况下,我已经毫无问题地做到了这一点。但是,我已经开始需要环顾四周,尽管我尽了最大努力,但现在我得到的匹配不正确。

这是正在评估的表达式:

hlhx=PRXPARSE('/yes|(?<!no).*homeless.*(for|in|year|age)|at\sage|couch|was\shomeless|multiple|
                        lived.*streets|(?<!\bnot).*at\srisk|has\sbeen|high\srisk|currently\shomeless|
                        liv(es|ing|ed).*car|many|(?<!\bno).*(hx|history|h.?o)|(?<!\bno)(?<!low).+risk/ox');

一些响应不应该匹配这个表达式,但是:

显然我没有正确指定我的回顾。任何帮助将不胜感激。

编辑:更准确地说,表达式的哪一部分与列表中的条目匹配?

最好的, 劳伦

下面是您的正则表达式如何匹配 no and little risk:

正则表达式中的一个分支是 ...|(?<!\bno)(?<!low).+risk

正则表达式引擎首先尝试在目标字符串中的每个位置进行匹配,从开头开始:

no and little risk
^

第一个限制条件是当前位置不能在单词边界前面加上"no"(由于(?<!\bno))。满足此条件:目标字符串的开头没有任何内容。

第二个限制条件是当前位置前面不能有"low"(由于(?<!low))。这个条件也满足(见上文)。

然后我们匹配一个或多个非换行符,但尽可能多(这是 .+ 部分)。在这里,我们最初使用整个字符串:

no and little risk
------------------^

但是正则表达式需要匹配 risk,这会失败(目标字符串中没有更多字符)。这导致 .+ 回溯并消耗越来越少的字符,直到发生这种情况:

no and little risk
--------------^

至此,risk匹配成功,正则表达式结束。

基本问题是你想做的是(?<!\bno.+)(?<!low.+)risk,但你写的却是(?<!\bno)(?<!low).+risk。这是两个截然不同的东西!

前者表示"match 'risk', but only if it's not preceded by 'no' or 'low' anywhere in the string (up to 1 character before 'risk')"。后者表示"match any non-empty substring followed by 'risk', as long as it's not preceded by either 'no' or 'low'"。这使正则表达式引擎可以自由地在字符串中查找任何匹配的位置,只要它不是紧跟在 "no" 或 "low" 之前并且在某处紧跟“.+risk”即可。

很遗憾,(?<!\bno.+) 不是有效的正则表达式,因为回顾断言必须具有固定长度。

一种可能的解决方法是执行以下操作:

^(?!.*(?:\bno|low).+risk).*risk

这是说:从字符串的开头开始,首先确保没有"no"或"low"后跟[=​​67=]的任何地方,然后匹配"risk"任何地方在字符串中。

这与(假设的)可变宽度后视版本不太等同,因为后者会匹配

risk no risk
^^^^

由于 "risk" 前面没有 "no",而此解决方法首先找到

risk no risk
     ^^^^^^^

并立即拒绝整个字符串。