手机版

使用正则表达式查找不包含特定字符串的条目

时间:2021-09-10 来源:互联网 编辑:宝哥软件园 浏览:

日志分析往往需要处理成千上万个日志条目,为了在海量数据中找到特定的数据模式,往往需要编写许多复杂的正则表达式。例如,枚举日志文件中不包含特定字符串的条目,找出不以特定字符串开头的条目,等等。

使用消极预见

正则表达式中有前瞻和后视的概念,生动地描述了正则引擎的匹配行为。需要注意的是,正则表达式前后和我们一般理解的前后有些不同。对于一段文字,我们通常把文字开头的方向称为“前”,把文字结尾的方向称为“后”。但是对于正则表达式引擎来说,因为它是从文本的头部到尾部进行解析的(解析方向可以通过正则选项来控制),所以文本的尾部方向叫做“前”,因为此时正则引擎还没有到达那个块,而文本的头部方向叫做“后”,因为正则引擎已经通过了那个块。如下图所示:

正向前瞻逆向前瞻

所谓前瞻,就是在正则表达式匹配某个字符时,先向前看“未解析的文本”,看它是否匹配/不匹配匹配模式,然后再向后看,也就是看已经被正则引擎匹配的文本,看它是否匹配/不匹配匹配模式。符合或不符合特定的匹配模式也称为正匹配和负匹配。

现代先进的正则表达式引擎一般都支持前瞻,但是对回溯的支持不是很广泛,所以我们在这里使用负前瞻来满足我们的需求。

实现

测试数据:

复制代码如下:2009-07-07 04:38336044 127 . 0 . 0 . 1 get/robots . txt 2009-07-07 04336038336044 127 . 0 . 0 . 1 get/post/robot file . txt 2009。

例如,上面这些简单的日志条目,我们希望实现两个目标:

1.过滤掉8号数据。2.找出不包含robots.txt字符串的条目(只要Url包含robots.txt,就将其过滤掉)。

前瞻性语法是:

(?匹配模式)让我们首先认识到,第一个目标——匹配不以特定字符串开头的条目。

这里我们要排除一个连续的字符串,所以匹配的模式很简单,就是2009-07-08。实施如下:

复制代码如下:(?2009-07-08).*?$

有了Expresso,我们可以看到8号的结果确实过滤掉了数据。

接下来,让我们实现第二个目标,——,排除包含特定字符串的条目。

根据我们上面写的,我画了瓢:

复制代码如下:*?(?机器人。txt)。*?$

这个正则化用白话来描述:从任意字符开始,然后不跟随robots.txt连续字符串,然后跟随任意字符,然后结束字符串。运行测试,发现:

image

它没有达到我们想要的。这是为什么?让我们在上面的正则表达式中添加两个捕获组进行调试:

复制代码如下:(。*?)(?机器人。txt)(。*?)$

测试结果:

image

我们可以看到第一个分组什么都不匹配,而第二个分组匹配整个字符串。回去分析一下刚才的正则表达式。事实上,当常规引擎解析到A区域时,它已经开始执行B区域的前瞻工作。这时发现当A区域为Null时,匹配成功,——。*最初允许匹配空字符,并且满足前瞻条件。A区之后是“2009”字符串,而不是机器人。因此,整个匹配过程成功地匹配了所有条目。

image

分析原因后,对上述规律进行了修正和改变。*?按如下方式移入前瞻表达式:

复制代码如下:(?*?机器人)。*$

测试结果:

image

完成

php中的常规实现不包括特定字符串的实现方法

preg_match('/^((?abc)。)*$/is ',$ str);

完整的代码示例

复制代码如下: $ str=' dfadfadf 765577 ABC 55 FD ';$pattern_url='/^((?abc)。)* $/is ';If (preg _ match ($ pattern _ URL,$ str)) {echo '不包含abc!';}else{echo '包含abc!';}

结果是:假用abc!

同时匹配且包含字符串“abc”但不包含字符串“xyz”的正则表达式:

preg_match('/(abc)[^((?xyz)。)*$]/is ',$ str);

这个方法很有效,我的用法如下:

(?(?\/div)。|\n)*?//匹配不带/div的字符串

但是在最后的使用中发现,这种方法的效率极低,在处理很短的词时可以考虑(正则表达式的同一个部分匹配的词有十几个,最多几十个),但是在分析大篇幅文章或者很多地方改变匹配时间时就不应该使用,而应该考虑其他方法(例如,首先分析要匹配正则表达式的单词,然后验证其中是否有某一段单词),正则表达式不包括用于匹配

版权声明:使用正则表达式查找不包含特定字符串的条目是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。