我为这个意想不到的负面前瞻子模式做了什么错误?

时间:2014-11-06 15:59:49

标签: regex regex-negation regex-lookarounds negative-lookahead

我实际上正在使用.tsv数据库,其标题对我来说充满了有意义的事情。

我因此想把它们从标题中删除到我和我之间的东西。其他用户(非熟练使用关系数据库,因此我们最终使用Excel来组织数据并对其进行处理)将能够更好地处理Excel,方法是用标签分解它们。

示例标题:

>(name1)database-ID:database2-ID:value1:value2

(我知道将值放在标题中似乎很奇怪,但这是描述与标题关联的第三个值的参数,我们不必在这里弄乱) 输出为:

name1\tdatabase-ID\tdatabase2-ID\tvalue1\tvalue2\n

因此我在EmEditor(BOOST语法)中粘贴了我的数据(标题,每行一个),并附带了这个正则表达式:

 >\((.*)\)(.*?)\:(.*?)\:(.*?)\:(.*?)\n

然后通过在彼此之间插入标签将每个捕获组与其他捕获组分开。它有效,完美匹配,没问题。

但是我意识到有错误的行没有尊重整个数据库的逻辑,我想做一个表达式来立即将它们分开。

如果我用错误的线条制作,那就是:

>(name1)database-ID:database2-ID:value1-1:value1-2\n
>(name2)database-ID:database2-ID:value2-1:value2-2\n
>(name3)database-ID:database2-ID:value3-1value3-2\n

最后一行格式不正确,因为它在最后两个值之间缺少:。 我希望通过解决识别格式良好的线条的原始表达式来匹配它。

我完全知道我可以通过稍微调整我的第一个表达式来消除良好的线条并在之后检索错误的一个表达式来提供不同的解决方案。 我不想要解决我的过程,我只是想了解我在那里做得不好;这样我就会受到更多的教育(而且不仅仅是因为能够绕过我无法解决的错误而变得更加棘手):

我试图否定上面提到的表达方式:

([^(>\((.*)\)(.*?)\:(.*?)\:(.*?)\:(.*?)\n)])

这与任何事情都不匹配。

我尝试了一个负向前瞻,但它会非常,非常缓慢,然后匹配文档中可能的每个0长度匹配:

(?!(^>\((.*)\)(.*?)\:(.*?)\:(.*?)\:(.*?)\n))

我因此为后面的一串字符添加了一个组捕获, 但它也不起作用:

(?!(^>\((.*)\)(.*?)\:(.*?)\:(.*?)\:(.*?)\n))(^.*?)

那么请解释一下我对否定小组([^whatever])和使用否定前瞻的错误?

3 个答案:

答案 0 :(得分:3)

您可以通过PCRE动词(*SKIP)(*F)完成此操作。以下正则表达式将匹配所有坏线。

(?:^>\([^()]*\):[^:]*:[^:]*:[^:]*:[^:\n]*$)(*SKIP)(*F)|^.+

DEMO

答案 1 :(得分:3)

  

那么请解释一下我对否定小组([^whatever])和使用否定前瞻的错误?

让我们先解决问题:[^(pattern)]做了什么?

你似乎有一种误解,并期望它:

  • 匹配除子模式pattern以外的所有内容。 (否定)

它实际上做的是:

  • 匹配任何非(pat,... n)的字符。< / LI>

因此,模式

([^(>\((.*)\)(.*?)\:(.*?)\:(.*?)\:(.*?)\n)])

...匹配不是(>(,... \n)的字符。


至于消极的前瞻,你只是做错了。锚^处于错误的位置,因此您的断言将无法提供任何有用的帮助。它也不是什么负面的前瞻性。

(?!(^>\((.*)\)(.*?)\:(.*?)\:(.*?)\:(.*?)\n))

我会解释这是做什么的:

  • (?!打开否定前瞻组:断言位置与此模式不匹配,不移动指针位置。
  • (捕获小组。在负前瞻组中使用捕获组是没用的,因为负前瞻组中的子模式永远不会匹配。
  • ^在字符串开头处断言位置。
  • >\(文字字符序列“&gt;(”
  • (.*)捕获除了换行符之外尽可能多的字符匹配的组,然后回溯。
  • \)字面字符“)”
  • (.*?)使用除换行符之外的任何字符的不情愿的零对一匹配来捕获组。
  • \:字面字符“:”
  • (.*?)\:(.*?)\:(.*?)
  • \n新行。
  • )关闭捕获组。
  • )关闭负向前瞻组。当这个断言完成时,指针位置与开始相同,因此得到的匹配是零长度。

请注意,锚点嵌套在负前瞻组中。它应该在开始时:

^(?!(>\((.*)\)(.*?)\:(.*?)\:(.*?)\:(.*?)\n))

虽然这不会返回任何有用的东西,但它解释了什么是错误的,因为您不需要解决方案。 ;)

如果您突然需要解决方案,请参阅我的相关答案(我没有在帖子中添加任何其他内容):

答案 2 :(得分:1)

基于我从Unihedron读到的内容; 这就是我在emEditor中的表现:

^(?!>\(([A-Za-z0-9_\'\-]*?)\)(([A-Za-z0-9_\'\-]*?)\:){3}([A-Za-z0-9_\'\-]*?)\n).*\n
>(name1)database-ID:database2-ID:value1-1:value1-2
(NOT MATCH)

>(name2)database-ID:database2-ID:value2-1:value2-2
(NOT MATCH)

>(name3)database-ID:database2-ID:value3-1value3-2
(MATCH)

>(name3)database-ID::database2-ID:value3-1:value3-2
(MATCH)

(字符类避免丢弃包含特殊字符的名称,但不能再有两个":"。)

我也可以用以下方法获得相同的结果:

(?!^>\(([A-Za-z0-9_\'\-]*?)\)(([A-Za-z0-9_\'\-]*?)\:){3}([A-Za-z0-9_\'\-]*?)\n)^.*\n

所以我猜所有捕捉小组都是我的前瞻。

现在我承认Avinash Raj(*SKIP)(*F)|^.+模式更有效,只是因为我不了解这些函数,我也想了解我的逻辑/语法错误。 (感谢Unihedron