繁体   English   中英

具有怪异怪异行为的正则表达式

[英]regex with lookbehind weird behavior

过去两天我一直试图解决这个问题......

请帮助我理解为什么会这样。 我的目的是只要选择<HDR>具有<DTL1 val="92">.....</HDR>

这是我的正则表达式

(?<=<HDR>).*?<DTL1\sval="3".*?</HDR>

输入字符串是:

<HDR>abc<DTL1 val="1"><DTL2 val="2"></HDR><HDR><DTL1 val="92"><DTL2 val="55"></HDR><HDR><DTL1 val="3"><DTL2 val="4"></HDR>

但这个正则表达式选择

abc<DTL1 val="1"><DTL2 val="2"></HDR><HDR><DTL1 val="92"><DTL2 val="55"></HDR>

谁能帮帮我吗?

正则表达式引擎将始终为您提供字符串中最左侧的匹配(即使您使用非贪婪的量词)。 这正是您获得的。

因此,解决方案是禁止在.*?描述的部分中存在另一个<HDR> .*? 这太宽容了。

你有两个技术要做,你可以替换.*? 有:

(?>[^<]+|<(?!/HDR))*

或者:

(?:(?!</HDR).)*+

大多数情况下,第一种技术性能更高,但如果你的字符串包含高密度的< ,第二种方法也可以产生很好的效果。

占有量词原子组的使用可以减少获得结果的步骤数,特别是当子模式失败时。

例:

第一种方式:

(?<=<HDR>)(?>[^<]+|<(?!/HDR))*<DTL1\sval="3"(?>[^<]+|<(?!/HDR))*</HDR>

或这个变种:

(?<=<HDR>)(?:[^<]+|<(?!/HDR|DTL1))*+<DTL1\sval="3"(?:[^<]+|<(?!/HDR))*+</HDR>

用第二种方式:

(?<=<HDR>)(?:(?!</HDR).)*<DTL1\sval="3"(?:(?!</HDR).)*+</HDR>

或这个变种:

(?<=<HDR>)(?:(?!</HDR|DTL1).)*+<DTL1\sval="3"(?:(?!</HDR).)*+</HDR>

Casimir et Hippolyte已经为您提供了几个很好的解决方案。 我想详细说明一些事情。

首先,为什么你的正则表达式无法做你想做的事情: (?<=<HDR>).*? 告诉它匹配以<HDR>开头的第一个字符开头的任意数量的字符,直到遇到非贪婪量词( <DTL1... )之后的<DTL1... 嗯,这是由后面的第一个字符<HDR>是第a ,所以它匹配一切从这里开始,直到固定字符串<DTL1\\sval="3"遇到。

Casimir et Hippolyte的解决方案适用于广义情况,其中<HDR>标签的内容可以是嵌套<HDR>以外的任何内容。 您也可以通过积极的预测来做到这一点:

(?<=<HDR>)(.(?!</HDR>))*<DTL1\sval="3".*?</HDR>

但是,如果字符串保证在显示的结构中,其中<HDR>标记只包含一个或多个<DTL1 val =“ ## ”>标记,那么您知道其中不会有任何结束标记,可以通过替换第一个来更有效地做到这一点.*? [^/]*

(?<=<HDR>)[^/]*<DTL1\sval="3".*?</HDR>

否定字符类比零宽度断言更有效, 如果使用否定字符类,则贪婪量词变得比惰性量词更有效。

另请注意,通过使用lookbehind匹配开头<HDR>,您将其从匹配中排除,但您要包括结束</ HDR>。 你确定那是你想要的吗? 你匹配这个......

<DTL1 val="3"><DTL2 val="4"></HDR>

......大概你想要这个......

<HDR><DTL1 val="3"><DTL2 val="4"></HDR>

...或这个...

<DTL1 val="3"><DTL2 val="4">

所以,在第一种情况下,不要使用lookbehind作为开始标记:

<HDR>(.(?!</HDR>))*<DTL1\sval="3".*?</HDR>
<HDR>[^/]*<DTL1\sval="3".*?</HDR>

在第二种情况下,使用预测结束标记:

(?<=<HDR>)(.(?!</HDR>))*<DTL1\sval="3".*?(?=</HDR>)
(?<=<HDR>)[^/]*<DTL1\sval="3".*?(?=</HDR>)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM