上一主题 下一主题
ScriptCat,新一代的脚本管理器脚本站,与全世界分享你的用户脚本油猴脚本开发指南教程目录
12下一页
返回列表 发新帖

正则表达式(?=.*[a-z])含义

[复制链接]
  • TA的每日心情
    慵懒
    2024-10-28 07:07
  • 签到天数: 193 天

    [LV.7]常住居民III

    712

    主题

    5959

    回帖

    6758

    积分

    管理员

    非物质文化遗产社会摇传承人

    积分
    6758

    荣誉开发者喜迎中秋油中2周年生态建设者

    发表于 2022-5-19 01:27:58 | 显示全部楼层 | 阅读模式

    Tips

    3楼有cxxjackie的理解
    非常清晰易懂并且薛劈入里!
    推荐大家详细品读

    开篇

    最近在学习正则的时候
    突然发现好多常见的正则表达式
    大家都在用,但是他妈的又是根本查不到中文资料....
    不知道为啥感觉中文编程环境随便一点基础问题资料缺乏的要命
    要不我好好学习正则再建个正则中文网吧(笑
    今天突然很好奇(?=.*[a-z])的意思
    (?=xxx)实际是一个环视断言语句
    ?=是向后查找字符串

    我爱你 我爱他
    我爱(?=你)
    这个时候只能检索到我爱你
    这种格式是
    表达式1(表达式2)
    那问题来了
    (?=. *[a-z])通常都是放在前边是怎么执行的?!
    这个问题我查了一晚上才搞明白
    大家可以参考
    https://stackoverflow.com/questions/2973436/regex-lookahead-lookbehind-and-atomic-groups
    我大概重述一下

    理论

    环视是一个零宽度断言,他们会检查正则表达式,在找到匹配的时候判断成功或失败来决定是否抛弃内容,同时它不消耗任何字符,后续的正则表达式会从相同的字符位置继续执行
    详情可以阅读
    http://www.regular-expressions.info/lookaround.html

    (?=表达式1)表达式2
    当表达式1匹配成功的时候,会从相同位置匹配表达式2
    那么我们现在再来看
    我爱(?=你)
    当匹配我爱你的时候
    首先找到我爱,然后发现环视表达式,看后方存在你,于是匹配成功
    而匹配我爱他的时候
    找到我爱后,发现后放不存在你,于是匹配失败。
    而假设我们调换顺序呢?

    (?=你)我爱
    这个表达式是否成立?
    大家可以开动你的小脑筋想一想
    当然成立!个鬼啦!怎么可能成立
    假设我们写一个你我爱
    首先找到环视表达式(?=你)
    找到了你字,然后保持原位置不变,开始搜寻我爱
    因为第一个字匹配成功,一定是一个你,所以不可能匹配上我爱
    也就是说这是一个失败的正则表达式
    那我们怎么改?
    (?=你)你我爱
    用来搜寻字符 【你我爱你】
    这样的表达式是成功的
    因为第一个字匹配成功,是一个你,然后原位置搜寻你我爱
    我们的字符是匹配的,所以匹配成功!
    那么接下来我们看正则表达式
    (?=.*[a-z])
    .*代表匹配任意字符0至任意一个宽度
    而a-z代表匹配一个小写字符a-z的任何一个
    一旦找到了小写字母,则认为表达式是成立的
    然后继续往后进行匹配
    那我们看一个比较长的表达式
    图片.png
    .*?这里的?代表是非贪婪模式
    第一个正则表达式搜寻是否存在小写字母
    第二个正则表达式搜寻是否存在大写字母
    而两个都成功
    则在原位置匹配字符了
    如果你看到这里相信你应该明白了环视表达式的计算方式了!

    结语

    撒花~

    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道

    入驻了爱发电https://afdian.net/a/lihengdao666
    个人宣言:この世界で私に胜てる人とコードはまだ生まれていません。死ぬのが怖くなければ来てください。
  • TA的每日心情

    2024-4-3 09:09
  • 签到天数: 12 天

    [LV.3]偶尔看看II

    8

    主题

    29

    回帖

    50

    积分

    初级工程师

    积分
    50
    发表于 2022-5-19 10:00:28 | 显示全部楼层
    正则表达式常用的规则如下:
    ^:表示开始
    $:表示结束
    [ ]:代表某个范围内的单个字符,比如: [0-9] 单个数字字符
    .:代表任意单个字符,除了换行和行结束符
    \w:代表单词字符:字母、数字、下划线(),相当于 [A-Za-z0-9]
    \d:代表数字字符: 相当于 [0-9]
    量词:
    +:至少一个
    *:零个或多个
    ?:零个或一个
    {x}:x个
    {m,}:至少m个
    {m,n}:至少m个,最多n个
    回复

    使用道具 举报

  • TA的每日心情
    慵懒
    2022-3-8 11:41
  • 签到天数: 2 天

    [LV.1]初来乍到

    22

    主题

    881

    回帖

    1379

    积分

    荣誉开发者

    积分
    1379

    荣誉开发者卓越贡献油中2周年生态建设者油中3周年挑战者 lv2

    发表于 2022-5-19 11:41:20 | 显示全部楼层
    我的理解是?=表达的是位置,即从字符串的某个位置开始匹配。先理解?<=,/(?<=a)bc/会首先找到a,然后以a为起点(不包括a)向后查找bc,换句话说,就是匹配以a开头的bc字符串,不包括a。?=非常相似,只是方向改成向前,/ab(?=c)/匹配以c结尾的ab字符串,不包括c。这主要涉及正则的捕获组,可以使某些字符串既在规则里,又不被捕获到,这在截取某些特征字符时比较有用,比如一段html,截取某个元素的文本,可以写成:/(?<=<div id="test">).*?(?=<\/div>)/。另一组语法是?<!和?!,是上面语法的否定,可以简单理解为匹配以某字符串开头/结尾的字符串。
    为什么说这些语法表达的是位置,当整段表达式都用?=括起来时,匹配结果会是空字符,这个空字符其实就表示了位置。js的replace函数,可以利用这个位置插入字符,参考以下例子来理解:
    1. 'abc'.replace(/(?<=b)/, 'd') //abdc
    2. 'abc'.replace(/(?=b)/, 'd') //adbc
    复制代码

    ?=是向前查找,一般放在表达式的后面,如果放在最前面,由于往前没有表达式,所以会先停到对应的位置,再开始向后匹配,比如:
    1. 'abc'.match(/(?=b).*/)[0]
    复制代码

    首先(?=b)会停在a和bc之间的位置,往后.*,结果匹配bc。值得注意的是,将?=前置很多时候是没有意义的,上面的正则可以直接改成/b.*/,类似于/(?=a)abc/这样的写法完全是废话。将?<=后置与这一情况类似。
    关于捕获组的概念,正则可以通过加括号来给结果分组,像match函数的结果就是一个数组,上面html的例子可以改写成:
    1. str.match(/<div id="test">(.*?)<\/div>/)[1]
    复制代码

    这种情况不需要用到?<=、?=,不分组的情况下这些语法才更有价值。比如一些文本工具(包括浏览器的F12)提供正则搜索,这种场景显然是不分组的,假设我们要在某段代码中搜索变量i,但i也可能夹杂在一串单词中间,可以写成:/(?<=\W)i(?=\W)/或/(?<!\w)i(?!\w)/
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2022-9-11 10:49
  • 签到天数: 19 天

    [LV.4]偶尔看看III

    13

    主题

    269

    回帖

    249

    积分

    版主

    积分
    249
    发表于 2022-5-19 09:59:18 | 显示全部楼层
    泻药,已经不认识`你`字了
    回复

    使用道具 举报

  • TA的每日心情
    慵懒
    2024-10-28 07:07
  • 签到天数: 193 天

    [LV.7]常住居民III

    712

    主题

    5959

    回帖

    6758

    积分

    管理员

    非物质文化遗产社会摇传承人

    积分
    6758

    荣誉开发者喜迎中秋油中2周年生态建设者

    发表于 2022-5-19 10:16:09 | 显示全部楼层
    水凛子 发表于 2022-5-19 09:59
    泻药,已经不认识`你`字了

    你不知道的船新版本
    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道

    入驻了爱发电https://afdian.net/a/lihengdao666
    个人宣言:この世界で私に胜てる人とコードはまだ生まれていません。死ぬのが怖くなければ来てください。
    回复

    使用道具 举报

  • TA的每日心情
    慵懒
    2024-10-28 07:07
  • 签到天数: 193 天

    [LV.7]常住居民III

    712

    主题

    5959

    回帖

    6758

    积分

    管理员

    非物质文化遗产社会摇传承人

    积分
    6758

    荣誉开发者喜迎中秋油中2周年生态建设者

    发表于 2022-5-19 10:16:26 | 显示全部楼层
    15533829110 发表于 2022-5-19 10:00
    正则表达式常用的规则如下:
    ^:表示开始
    $:表示结束

    正则写着太累了...
    呜呜呜
    每次写正则跟做高数一样
    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道

    入驻了爱发电https://afdian.net/a/lihengdao666
    个人宣言:この世界で私に胜てる人とコードはまだ生まれていません。死ぬのが怖くなければ来てください。
    回复

    使用道具 举报

  • TA的每日心情
    慵懒
    2024-10-28 07:07
  • 签到天数: 193 天

    [LV.7]常住居民III

    712

    主题

    5959

    回帖

    6758

    积分

    管理员

    非物质文化遗产社会摇传承人

    积分
    6758

    荣誉开发者喜迎中秋油中2周年生态建设者

    发表于 2022-5-19 14:53:41 | 显示全部楼层
    cxxjackie 发表于 2022-5-19 11:41
    我的理解是?=表达的是位置,即从字符串的某个位置开始匹配。先理解?

    读了好几遍
    如果早看到估计直接就明白了
    不用那么费劲找资料了...呜呜呜
    哥哥讲的比市面上的正则教程清晰多了
    对环视的理解加强了!
    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道

    入驻了爱发电https://afdian.net/a/lihengdao666
    个人宣言:この世界で私に胜てる人とコードはまだ生まれていません。死ぬのが怖くなければ来てください。
    回复

    使用道具 举报

  • TA的每日心情
    开心
    10 小时前
  • 签到天数: 709 天

    [LV.9]以坛为家II

    5

    主题

    39

    回帖

    501

    积分

    荣誉开发者

    积分
    501

    新人报道油中2周年荣誉开发者生态建设者油中3周年挑战者 lv2

    发表于 2022-5-20 08:44:36 | 显示全部楼层
    推荐好用的一个正则测试和调试的网站 https://regex101.com/
    回复

    使用道具 举报

  • TA的每日心情
    慵懒
    2024-10-28 07:07
  • 签到天数: 193 天

    [LV.7]常住居民III

    712

    主题

    5959

    回帖

    6758

    积分

    管理员

    非物质文化遗产社会摇传承人

    积分
    6758

    荣誉开发者喜迎中秋油中2周年生态建设者

    发表于 2022-5-20 09:17:25 | 显示全部楼层
    airbeyond 发表于 2022-5-20 08:44
    推荐好用的一个正则测试和调试的网站 https://regex101.com/

    这个确实好用!
    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道

    入驻了爱发电https://afdian.net/a/lihengdao666
    个人宣言:この世界で私に胜てる人とコードはまだ生まれていません。死ぬのが怖くなければ来てください。
    回复

    使用道具 举报

  • TA的每日心情
    慵懒
    13 小时前
  • 签到天数: 811 天

    [LV.10]以坛为家III

    31

    主题

    552

    回帖

    1555

    积分

    荣誉开发者

    积分
    1555

    荣誉开发者新人进步奖油中2周年生态建设者新人报道挑战者 lv2油中3周年喜迎中秋

    发表于 2022-7-2 17:43:47 | 显示全部楼层

    之前在其他地方看到一个很有意思的正则,至今还是没看懂,
    需求:将一个字符串按3位数为1组切割
    比如"aaabbbcccdddeeefffggghh"
    我的写法是,直接用match匹配3个字符,如果字符串长度不是3的倍数那么会剩余1\~2个字符再通过字符串结尾匹配就行了

    > "aaabbbcccdddeeefffggghh".match(/.{3}|.{1,2}$/g)
    < (8) ['aaa', 'bbb', 'ccc', 'ddd', 'eee', 'fff', 'ggg', 'hh']

    别人的写法是直接split 3个字符后面的""空字符(至今没看懂这是怎么匹配上的)

    > "aaabbbcccdddeeefffggghh".split(/(?<=^(?:...)*)/)
    < (8) ['aaa', 'bbb', 'ccc', 'ddd', 'eee', 'fff', 'ggg', 'hh']

    虽然殊途同归,但我还是想弄清楚这个原理,不知道GG有什么见解?

    回复

    使用道具 举报

    发表回复

    本版积分规则

    快速回复 返回顶部 返回列表