RegEx如何根据特定位置的字符否定匹配

3
请注意:我正在使用Python(版本3.6)进行编程,但也希望将这些正则表达式移植到SAS中。
大致情况是,我正在处理一个SAS日志,并且希望排除来自%include语句的打印在日志中的行。基本上,我想要实现的效果如下:
54210      proc sort data=inds out=outds;

我不想要的行将会是这样:

33406     +%global  var1 var2 var3;

重点在于第11个字符将是“+”,但是左侧始终会有一组数字,后跟一组空格,其长度最终将为11个空格-除非它是一个%include行,我要将其排除。
到目前为止,我拥有的是这样的内容:
^[0-9]{1,11} (?! {2,10}\+)

这种方法在我测试的日志中能够完全抓取我想要的内容,但是它并不完美。采用以下表达式是一个简单的解决方法:

^[0-9]{1,11} {3,10}

然后添加一个额外的条件,如果第11个字符是“+”,则忽略该行,但我可以在单个正则表达式中完成这个操作吗?我在处理此问题时遇到了前瞻/后顾,但问题在于第一匹配的组长度可能会变化,这就使得预期的“+”的位置发生了变化 - 所以我能否在一定长度内匹配一组,然后如果其后跟一个字符,则否定匹配?


^[0-9]{1,11} {3,10} 已经确保第11个字符不是 + - Wiktor Stribiżew
1
抱歉,您能解释一下“锁定前瞻后的第二部分,以严格捕获N个数字后跟M个空格,其中N + M == 1”的意思吗?您是想仅匹配数字或空格总和为10的块吗?我认为提供两三个示例并说明每个示例的预期输出会有所帮助。 - Wiktor Stribiżew
在SAS日志文件中,我要查找的行始终是一个行计数器,后面跟着空格,并且在找到任何其他字符之前总长度为11。因此,请参阅以下链接:https://regex101.com/r/m24BZk/2 - Michael Stackhouse
要明确的是,我认为你给我的东西非常充足,所以我认为这是一个非常令人满意的答案。但请看 https://regex101.com/r/qp44lN/4 中的最后一行。如果 a) 字符串至少有11个字符,b) 它以数字开头,c) 该数字后面跟着一个空格,则在前11个字符中可能会有第二个数字,它仍然会匹配。此时,我只是好奇这个表达式是否可以万无一失。 - Michael Stackhouse
这对我来说看起来很好 - 我曾经尝试过类似的回顾,但你修复了第一部分,这就锁定了它。非常感谢!!! - Michael Stackhouse
显示剩余7条评论
3个回答

1

您可以使用

^\d+ +(?<=.{11})

请查看正则表达式演示

细节

  • ^ - 字符串开头
  • \d+ + - 1个或多个数字,然后是1个或多个空格
  • (?<=.{11}) - 正向后瞻检查,要求当前位置左侧恰好有11个字符。

只是想从您在原始问题的评论中添加一些内容(因为这解决了我的问题,但我的问题是基于特定位置的字符否定匹配),此表达式成功地根据+的位置否定了匹配:^(?!.{10}\+)(?=[\d ]{11}(?! ))\d+ +,其中初始负向前瞻^(?!.{10}\+)针对第11个位置的+。再次感谢! - Michael Stackhouse

0

您可以使用^[0-9\s]{,11}\+来丢弃不需要的日志。它匹配最多11个数字和/或空格,后跟一个+(这似乎是不需要的项目的模式)。如果您想要否定匹配,只需执行not re.match(...)

使用前瞻,您可以拒绝包含其前11个字符中包含+的字符串,然后匹配所需的模式:^(?=[^+]{11})[0-9]{1,11} {3,10}

(?=      # Look ahead and assert equal that ...
   [^+]  # ... anything but a plus ...
   {11}  # ... matches the following 11 characters.
)

这有所帮助,但仍不是我想要的完全的解决方案,因为它总是数字后面跟着空格。这允许数字和空格可以互换。而我明确希望匹配,但如果"+"是第11个字符,则否定匹配。因此,在这种情况下,重要的是匹配类似54210 proc sort data=inds out=outds;这样的内容,但不匹配33406 +%global var1 var2 var3; - Michael Stackhouse
@MichaelStackhouse 这是否意味着+符号总是在第11个位置?那么有什么阻止你捕获它并检查相应的组(或者更简单地说,string[10] == '+')?你可以使用前瞻来断言前11个字符中没有一个是+符号(请参考我的更新答案)。这对你有帮助吗?无论如何,你可以使用两个正则表达式,一个用于“白名单”所需的日志,另一个用于“黑名单”不需要的日志,然后执行if not blacklisted and whitelisted: ... - a_guest
我正在排除第11个位置有+的行,但这只是将?=反转为?!!=的简单操作,就像你上面列出的一样。是的,你回答的内容与Wiktor在我的原始问题的评论线程中回答的内容非常相似,而且那个方法也可行。所以我可以使用类似的策略。另外,是的,我可以简单地添加第二个条件,但出于自己的学习目的,我想尝试将所有内容都包装到一个表达式中。我最困扰的部分可以在上面的评论线程中看到。 - Michael Stackhouse
我在这个链接中保存了一个表达式和示例字符串以进行测试:https://regex101.com/r/m24BZk/2 - Michael Stackhouse

0

我对此无法控制我的客户,因为所有日志选项都在他们的autoexec中预设(巧合的是,我试图过滤掉的那些行)并且需要根据他们的SOP进行定义。他们开启了比我想看到的更多的选项。 - Michael Stackhouse

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接