• 【MedusaSTears】正则表达式搜索心得


    心得体会

    前情回顾:
    【MedusaSTears】正则?不要太简单!—正则表达式个人学习心得总结:

    1. 正则说白了是对字符串的整理,所以对一个无间隙长串,第一步最主要的就是,【分割】字符串,类似于英语的自然拼读法那种,从业务需求方面,理解并分割字符串
      比如: 邮箱为什么要以@前后分界?谁告诉你的?因为你知道这是默认的,然而这恰恰是容易被忽略的重点
    2. 正确【分割】后,就不难找到关键字符或者关键位置,也就是可能需要replace的地方,这是启动的核心,下手的第一步
    3. 对于不确定的字符串长度,先找到可以确定的或者唯一的部分
    4. 贪婪匹配 vs 懒惰匹配:
      默认情况下,正则表达式使用最长匹配原则(也叫贪婪匹配原则)。
      懒惰匹配: 在量词*、+、?、{n}、{n,}、{n,m}后面加?就是懒惰模式,懒惰对应的就是匹配的尽可能少的情况。
    5. 注意 ? * + {1,32} 这些量词实际上包括本身
    6. 注意 . 不包括\n \r
    7. 注意 . 是任意单个字符, [] 是指定中括号内的字符
    8. ?:是忽略分组,也就是说括号内的内容不是一个group,包括在实际匹配,用处是 取值的时候忽略这个组合


    需求: 查找指定字符之前/之后 的str, 且不包括条件里面的字符串
    举例: 想要 hello world 标签里面的内容
    答案: (?<=\<[tT][iI][tI][lL][eE]>).*?(?=)
    解析: 如果跟位序有关,则务必用 前瞻(Lookahead) ?= 或者 后顾(Lookbehind) ?<=
    后顾性能损耗比较大,js只支持前瞻(知乎上看到的,具体原因不详)
    本题是 查找指定字符串之后和之前的内容

    前瞻分两种:一种是正向前瞻 positive lookahead(?=xxx) 其后必须存在的内容,是一个条件,不是实际匹配中的内容
    另一种是负向前瞻 negative lookahead(?!xxx)
    ?= 是前瞻, 也就是计算机从左到右读取第n位字符的时候,n右侧的都是?=

    1.懒惰匹配最少字符 .+?

    1. 注意 . 不包括\n \r
    2. 注意 . 是任意单个字符, [] 是指定中括号内的字符


    +是至少出现1次 .+的意思:至少1个字符
    比如: hello.+friend返回的结果是: 字符串中 命中 hello开头,friend结尾的最长字符串,但是 hellofriend 中间,必须至少有一个字符,不存在 hellofriend这种情况

    ?则代表懒惰匹配,将.+匹配长度最小化
    比如:字符串hellomyfriendweareallfriends,
    如果用hello.+friend匹配就是不包括最后s的整个字符串hellomyfriendweareallfriend;
    如果用hello.+?friend匹配,结果就是命中第一个friend就停止的 hellomyfriend

    那么问题来了: .*?又表示什么意思呢?

    2.前瞻: 字符串后边 包括/不包括 某个单词/字母

    这里之所以 配合 .+? 进行查询条件,是因为括号中的条件,和前面的字符串并不是相邻的,中间隔着至少1个字符及以上

    2-1.包含某单词: start(?=.+?hello)

    查找start单词,并且后边要包括hello这个单词
    实际应用:
    定位日志中,Instagram的category是call的:
    instagram(?=.+?category=call)

    2-2.不包含某单词: start(?!.+?hello)

    参考资料: 正则表达式:不包含某个单词

    查找start单词,但是后边不包括hello这个单词
    实际应用:
    定位日志中,Instagram的category≠call的:
    instagram(?!.+?category=call)

    注意:输出结果只是括号前的东西,括号里的只是if条件

    2-2-1.更新2023-12-12: 如果想要找 先不包含某个单词,后又包含某个单词,且他俩还挨着呢?

    实际应用:
    定位日志中,含有Instagram的行,第一个出现的action且前面不是category=call的日志行:
    分析一下就就是:

    Instagram–>任意字符–>category=call acttion
    后边的category=call acttion 可以是 category=msg action,也可以压根没有category

    注意:

    1. 正常日志打印中 category=call action= 是紧挨着的
    2. 正常日志打印中 category=msg actions=2 vis=PRIVATE semFlags=0x0 semPriority=0 semMissedCount=0)) ;actionButton1 name 这一句中,有两个action

    实际测试输出:

    1. 关键词:instagram.*((?!category)action),查找结果:
      在这里插入图片描述
      可以看到:
      1. .*依然是最长匹配规则
      2. 第一个action前面有category
    1. 关键词:instagram.+?((?!category)action),将上一个例子中的.*修改成了.+?,查找结果: 在这里插入图片描述
      可以看到:
      1. .+?是最短匹配,到第一个action就停止了
      2. 第一个action前面有category
      3. 和示例1对比不难发现:这俩都没有生效(?!category),所以怀疑(?!category)action外侧的括号,引起的问题。
    1. 关键词:instagram.+?(?!category)action,将上一个例子中的外侧括号给去掉了,查找结果和示例二相同
      可以看到:
      1.并非是分组的问题,因为(?!category)action这个字符串的含义,可以更加深刻去理解:匹配action,并且他的前边不是category,也就是唯独排除categoryaction这种情况
    1. 关键词:instagram.+?(?!category=call )action,将上一个例子中的(?!category)修改成了(?!category=call ),查找结果依旧和示例二相同。
      可以看到:
      1. 本以为是紧挨着的匹配规则,但是查找结果依旧没变。
    1. 关键词:instagram.+?(?!.*category=call )action,将上一个例子中的(?!category=call )修改成了(?!.*category=call ),查找结果依旧和示例二相同。
      可以看到:
      1. 猜测是定义的懒惰匹配规则,但是在后续重申规则似乎也不好使
    1. 关键词:instagram.+?((?!category=call )action),将示例4中的(?!category=call )action加层括号,让他们成为"一组"条件。,查找结果依旧和示例二相同。
      可以看到:
      1. 通过和示例3做比对,发现:加不加最外层条件括号没有影响
    1. 关键词:instagram(?!.*category=call ).+?action,将上一个例子中的分组规则修改,(?!.*category=call )这个作为条件,采取最长匹配规则;.+?action最短匹配到action是我们的目的,查找结果终于有了变化: 在这里插入图片描述
      可以看到:

      1. 确实满足action的懒惰匹配,同时最前面的不是category=call
      2. 但是这个表达式,我理解更像是把(?!.*category=call )当成一个从左侧instagram到右侧第一个出现的action中间的滑动窗口,而不是紧挨着第一个action而定义出来的。

      PS: 针对以上猜测,我把查询出来的这个结果,手动修改成了category=call category=msg actions=2
      如果还能查询出来上面这条,就说明还真不是滑动属性的,但也绝对不是紧挨着的,这个我敢肯定。
      搜索的结果是:

      1. 确实 示例7 那条被我改成category=call category=msg actions=2的那条找不到了
      2. 所以再次说明: 示例7 这个表达式的含义是 查找instagram和第一个出现的action中间没有category=call 的日志行,
      3. 并不是action紧挨着的前面字符串,不是category=call 的日志行

    2-2-2.最终解决表达式:instagram(?!.*category=call action).+?action

    既然(?!.*category=call action)已经作为滑动窗口了,那就把边界字符串,或者可以固定它位置的字符串也带上,这样就不会滑动了
    示例7后边修改之后的日志,用这个表达式也可以搜索到了

  • 相关阅读:
    【SV中的多线程fork...join/join_any/join_none】
    EPICS记录参考--sub-Array记录(subArray)
    纯技术程序员的悲哀和出路
    面试常问:HTTPS的加密过程 ----- 光明和黑暗的恩怨情仇
    【笔试】2022/9/4 网易互联网开发岗满分
    Spring 事务传播机制源码浅析
    门窗软件项目---竖中梃类
    数据生产流程——采集、清洗、分析
    Linux 文本处理命令 - chmod
    Python函数式编程(三)操作符函数(operator)
  • 原文地址:https://blog.csdn.net/MedusaSTears/article/details/134078464